1-06-3 内部类

last modified: 2020/10/31

6.4 内部类

  • 内部类(inner class)是定义在另一个类中的类。
  • 使用的主要原因是:
    • 内部类方法可以访问该类定义坐在的作用域中的数据,包括私有的数据。
    • 内部类可以对同一个包中的其他类隐藏起来。
    • 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷。
6.4.1 使用内部类访问对象状态
  • 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域
  • 内部类的对象总是有一个隐式引用,它指向了创建它的外部类对象。
    • 这个引用在内部类的定义中时不可见的
  • 外围类的引用在构造器中设置。
    • 编译器修改所有的内部类的构造器,添加一个外围类引用的参数。
  • 只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性
6.4.2 内部类的特殊语法规则
  • 外围类引用表达式

    OuterClass.this

  • 可以采用下列语法格式更加明确地编写内部对象的构造器:
    outerObject.new InnerClass (construction parameters)

    • 例如,ActionListener listener = this.new TinePrinter0;
      在这里,最新构造的TimePrinter对象的外围类引用被设置为创建内部类对象的方法中的this引用。这是一种最常见的情况。通常,this 限定词是多余的。
  • 不过,可以通过显式地命名将外围类引用设置为其他的对象

  • 需要注意,在外围类的作用域之外,可以这样引用内部类:
    OuterClass. InnerClass

  • 内部类中声明的所有静态域都必须是final。 原因很简单。我们希望一个静态域只
    有一个实例,不过对于每个外部对象,会分别有一个单独的内部类实例。如果这个域不是final,它可能就不是唯一的。

  • 内部类不能有static方法。Java 语言规范对这个限制没有做任何解释。

6.4.3 内部类是否有用、必要和安全(!!!)
  • 内部类是一种编译器现象,与虚拟机无关。编译器将会把内部类翻译成用$ (美元符号)分隔外部类名与内部类名的常规类文件,而虚拟机则对此一无所知。
6.4.4 局部内部类
  • 局部类不能用public或private访问说明符进行声明。
    • 它的作用域被限定在声明这个局部类的块中。
  • 局部类有一个优势,即对外部世界可以完全地隐藏起来。即使TalkingClock类中的其他
    代码也不能访问它。除start方法之外,没有任何方法知道TimePrinter类的存在。
6.4.5 由外部方法访问变量
  • 与其他内部类相比较,局部类还有一个优点。
    • 它们不仅能够访问包含它们的外部类,还可以访问局部变量
    • 不过,那些局部变量必须事实上为final。这说明,它们一旦赋值就绝不会改变。
    • 在JAVA SE 8之前,必须把局部类访问的局部变量声明为fianl
6.4.6 匿名内部类
  • anonymous inner class

  • 通常的语法格式为:
    new Super Typel(construction parameters)

    {

    inner class methods and data
    }

    • 其中,SuperType 可以是ActionListener这样的接口,于是内部类就要实现这个接口。
    • SuperTlype也可以是一个类, 于是内部类就要扩展它。
  • 由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器。
    取而代之的是,将构造器参数传递给超类( superclass)构造器。尤其是在内部类实现接口的时候,不能有任何构造参数。不仅如此,还要像下面这样提供一组括号:
    new InterfaceType()

    {

      ***methods and data***
    

}

  • 多年来,Java程序员习惯的做法是用匿名内部类实现事件监听器和其他回调。如今最好
    还是使用lambda表达式。
6.4.7 静态内部类
  • 有时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用
    外围类对象。为此,可以将内部类声明为static,以便取消产生的引用。
  • 当然,只有内部类可以声明为static。静态内部类的对象除了没有对生成它的外围类对象
    的引用特权外,与其他所有内部类完全一样。
  • 在内部类不需要访问外围类对象的时候,应该使用静态内部类。有些程序员用嵌套类(nested class)表示静态内部类。
  • 与常规内部类不同,静态内部类可以有静态域和方法
  • 声明在接口中的内部类自动成为static和public类。
原文地址:https://www.cnblogs.com/nojacky/p/13909182.html