[学习笔记][Java编程思想]第10章:内部类

  • 内部类允许你把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。

1 创建内部类

  • 创建内部类的方式是把类的定义置于外围类的里面。
  • 外部类可以有一个方法,该方法返回一个指向内部类的引用。
  • 从外部类的非静态方法之外的任意位置创建某个内部类的对象,需要具体地指明这个对象的类型:OuterClassName.InnerClassName。

2 链接到外部类

  • 内部类还拥有其外围类的所有元素的访问权。
  • 内部类的对象只能在与其外围类的对象相关联的情况下才能被创建(在内部类是非static类时)。
  • 构建内部类对象时,需要一个指向其外围类对象的引用,如果编译器访问不到这个引用就会报错。

3 使用.this和.new

  • 内部类中,在外部类的名字后面紧跟圆点和this,可以生成对外部类对象的引用。
  • 创建内部类对象必须使用外部类对象的引用,并使用.new语法。
  • 在拥有外部类对象之前是不可能创建内部类对象的,这是因为内部类对象会暗暗地连接到创建它的外部类对象上。

4 内部类与向上转型

  • private内部类向上转型,可以完全阻止任何依赖于类型的编码,并且完全隐藏了实现的细节。
  • 外围类也拥有内部类的所有元素的访问权。
  • You cannot access the synthesized default constructor from ProtectedInnerClass because it has the same protected access as the defining class.

5 在方法和作用域内的内部类

  • 可以在一个方法里面或者任意的作用域内定内部类。
    • 实现了某类型的接口,可以创建并返回对其的引用。
    • 创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的。
  • 匿名类不可能有构造器。
  • 可以在同一个子目录下的任意类中对某个内部类使用相同的类标识符,这并不会有命名冲突。

6 匿名内部类

  • 方法可以将返回值的生成与表示这个返回值的类的定义结合在一起。
  • 如果匿名内部类的基类需要一个有参数的构造器,只需简单地传递合适的参数给基类的构造器即可。
  • 在匿名内部类末尾的分号,并不是用来标记此内部类结束的,实际上标记的是表达式的结束。
  • 如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用是final的。
  • 在匿名类中不可能有命名构造器,但通过实例初始化,就能够达到为匿名内部类创建一个构造器的效果。
  • 匿名类必须扩展类和实现接口,不能两者兼备。如果实现接口,也只能实现一个接口。

6.1 再访工厂方法

  • 优先使用类而不是接口。如果你的设计中需要某个接口,你必须了解它。

7 嵌套类

  • 不需要内部类对象与其外围类对象之间有联系,可以将内部类声明为static,称为嵌套类。
  • 不能从嵌套类的对象中访问非静态的外围类对象。
  • 普通内部类的字段和方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段。
  • You can refer to just the class name when inside the method of a class with a defined nested (static inner) class, but outside the class, you must specify the outer class and nested class, as shown in Other, above.

7.1 接口内部的类

  • 嵌套类可以作为接口的一部分,放到接口中的任何类都自动地是public和static的。
  • Nested has no added access to the elements of WithNested.实现含有嵌套类的接口的导出类,没有权限访问接口的嵌套类。

7.2 从多层嵌套类中访问外部类的成员

  • 一个内部类被嵌套多少层并不重要,它能透明地访问所有它所嵌入的外围类的所有成员。

8 为什么需要内部类

  • 内部类提供了某种进入其外围类的窗口。
  • 每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
  • 内部类允许继承多个非接口类型。
  • 内部类特性。
    • 内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外围类对象的信息相互独立。
    • 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。
    • 内部类并没有令人迷惑的“is-a”关系,它就是一个独立的实体。

8.1 闭包和回调

  • 闭包(closure)是一个可调用对象,它记录了一些信息,这些信息来自于创建它的作用域。
  • 内部类是面向对象的闭包,它不仅包含外围类对象(创建内部类的作用域)的信息,还自动拥有一个指向此外围类对象的引用。
  • 回调(callback),对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。
  • 当创建了一个内部类时,并没有在外围类的接口中添加东西,也没有修改外围类的接口。
  • 回调的价值在于它的灵活性,可以在运行时动态地决定需要调用什么方法。

8.2 内部类与控制框架

  • 应用程序框架是被设计用以解决某类特定问题的一个类或一组类。
  • 设计模式总是将变化的事物与保持不变的事物分离开。
  • 控制框架是一类特殊的应用程序框架,它用来解决响应事件的需求。主要用来响应事件的系统被称作事件驱动系统。图形用户接口(GUI),它几乎完全是事件驱动的系统。
  • 内部类允许:控制框架的完整实现是由单个的类创建的;内部类能够很容易地访问外围类的任意成员。

9 内部类的继承

  • 内部类的构造器必须连接到指向其外围类对象的引用。
  • 指向外围类对象的“秘密的”引用必须被初始化,而在导出类中不再存在可连接的默认对象。
  • 继承内部类,当要生成一个构造器,不仅要传递一个指向外围类对象的引用,还要在构造器内部添加enclosingClassReference.super()

10 内部类可以被覆盖吗

  • 当继承了某个外围类时,再在导出类定义一个同名的内部类。这两个内部类是完全独立的两个实体。
  • 可以通过导出类的实例,new出基类的内部类。

11 局部内部类

  • 使用局部内部类而不是匿名内部类的理由。
    • 需要一个已命名的构造器,或者需要重载构造器。而匿名内部类只能用于实例初始化。
    • 需要不止一个该内部类的对象。

12 内部类标识符

  • 每个类都会产生一个.class文件,其中包含了如何创建该类型的对象的全部信息。
  • 内部类类文件命名规则:外围类的名字,加上“$”,再加上内部类的名字。
  • 如果编译器是匿名的,编译器会简单地产生一个数字作为其标识符。
  • 如果内部类是嵌套在别的内部类之中,只需直接将它们的名字加在其外围类标识符与“$”的后面。

你可能感兴趣的:(java)