java编程思想读书笔记----第十章 内部类

来源:互联网 发布:淘宝货源网 编辑:程序博客网 时间:2024/06/05 20:27

1、创建内部类

  将类的定义置于外部类的里面,在外部类中可以直接new一个内部类的事例,通常外部类会有一个方法,该方法会返回一个指向内部类的引用。如果从外部类非静态方法之外的位置创建某个内部类的对象,必须具体的指明这个对象的类型:OutClassName.InnerClassName。

2、链接到外部类

  当生成一个内部类对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问外围类的所有成员,而不需要任何特殊条件。此外,内部类还拥有对外部类所有元素的访问权
  这是如何做到的呢?当某个外围类的对象创建了一个内部类对象时,此内部类对象会秘密捕获一个指向外围类对象的引用。然后,在你访问外围类的成员时,就是用那个引用来选择外围类的成员。内部类的对象只能在与其外部类对象相关联的情况下才能创建(在内部类是非static时)。

3、使用this和new

  如果需要生成对外部类的引用,可以使用在外部类后面紧跟小圆点和this。要想直接创建内部类的对象,必须使用外部类的对象来创建该内部类的对象,即在new表达式中提供外部类对象的引用。但是,如果创建的是嵌套类(静态内部类),那么就不需要对外部类对象的引用。

4、内部类与向上转型

  当将内部类向上转型为其基类,尤其是接口时,可以很方便地隐藏实现细节

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

  之前所看到的是内部类的典型用途,然而,内部类语法覆盖了大量其它的难以理解的技术。例如,可以在一个方法内或者在任意作用域内定义内部类。这么做有两个理由

  1. 如前所示,你实现了某类型的接口,于是创建并返回对其的引用。
  2. 你要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但又不希望这个类是公共可用的。

  内部类可能会出现一下几种情况

  • 一个定义在方法中的类
  • 一个定义在作用域内的类,此作用域在方法的内部
  • 一个实现了接口的匿名类
  • 一个匿名类,它扩展了有非默认构造器的类
  • 一个匿名类,它执行字段初始化
  • 一个匿名类,它通过实例初始化实现构造(匿名类不可能有构造器)

  内部类被定义在作用域内,并不表示类的创建是有条件的,而是在该作用域外,类是不可用的。
  匿名内部类,“创建一个实现了某个接口的匿名类的对象”,通过new表达式返回的对象被自动向上转型为接口类型。如果基类需要一个有参数的构造器,只需简单的传递合适的参数给基类构造器即可:new Wrapping(x)。如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求参数是final的。在匿名内部类中不可能有命名构造器,但可以通过实例初始化达到为匿名内部类创建一个构造器的效果,不能重载实例初始化方法。
  匿名内部类与正规的继承相比有所局限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者皆备。而且如果是实现接口,也只能实现一个接口。

6、嵌套类

  如果不需要内部类对象和其外围类对象有联系,可以将内部类声明为static,这通常称为嵌套类。普通的内部类对象隐式地保存了一个引用,指向创建它的外围类对象。然而,当内部类是static时就不是这样了,嵌套类意味着:

  • 要创建嵌套类对象,并不需要外部类对象
  • 不能从嵌套类对象中访问非静态的外围类对象

  嵌套类和普通内部类还有一个区别,非静态内部类不能有静态数据和静态方法,也不能包含嵌套类。

  接口内部的类:正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分。放在接口中的任何类都是自动public和static的。因为类是static的,所以只是将嵌套类置于接口的命名空间内。甚至可以在内部类中实现其外围接口。

7、为什么需要内部类

  内部类实现接口和外围类实现接口有什么区别呢,答案是:后者不能总是享用到接口带来的方便,有时需要用到接口的实现。所以内部类最吸引人的地方就是:每个内部类都能独自的继承一个(接口的)实现,所以无论外围类是否已经继承了某一个(接口的)实现,对于内部类都没有影响。
  内部类使得多重继承的解决方案变得完善。接口解决了部分问题,而内部类有效的实现了“多重继承”。内部类允许继承多个非接口类型(类或者抽象类)。
  使用内部类还可以获得一些其他的特性:

  1. 内部类可以有多个实例,每个实例都有自己的信息状态,且与外围类对象的信息相互独立。
  2. 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。
  3. 创建内部类对象的时刻并不依赖外围类对象的创建。
  4. 内部类没有令人疑惑的“is-a关系”,它是独立 的个体。

  通过内部类完成闭包和回调。
  内部类与控制框架,应用程序框架是用于解决某类特殊问题的一个类或者一组类。要运用某个程序框架,通常是继承一个或多个类,并覆盖某些方法。模板方法包含算法的基本结构,并且会调用一个或多个可覆盖的方法,以完成算法的动作。设计模式总是将变化的事物和保持不变的事物相分离,在这个模式中,模板方法是不变的事物,而可覆盖的方法是变化的事物。
  “将变化的事物和保持不变的事物分开”,变化的意思就是各种不同的Event对象拥有不同的行为,而你通过创建不同的Event子类来实现不同行为,这正是内部类要做的事,内部类允许:

  • 内部类的实现是通过单个类创建的,从而使得实现的细节被封装了起来。内部类用来表示解决问题的不同的action();
  • 内部类可以很容易的访问外围类的成员

8、内部类的继承

  因为内部类的对象必须连接到指向其外围对象的引用,该引用必须被初始化,而在导出类中不再存在可链接的默认对象,必须要使用特殊的语法来说明这个关系。

enclosingClassReference.super()

9、内部类可以被覆盖吗

  如果创建了一个内部类,然后继承其外围类并重新定义此内部类时会发生什么?当继承某个外部类时,该内部类并没有发生什么特别神奇的变化。这两个内部类是完全独立的两个实体。当然,明确的继承某个内部类也是可以的。

10、局部内部类

  前面提到过,可以在代码块里创建内部类,最典型的就是在一个方法体里面创建内部类。局部内部类不能有类访问权限,因为它不是外围类的一部分;但它可以访问当前代码块内的常量,以及此外围类的所有成员。
  局部内部类和匿名内部类有相同的行为和能力。既然局部内部类在方法外是不可见的,为什么仍然要使用局部内部类而非匿名内部类呢?唯一的理由是,我们需要一个已命名的构造器,或者需要重载构造器,而匿名内部类只能用于实例初始化。

  内部类也必须生成一个.class文件来包含class对象的信息,这些类文件有严格的命名规则:outerClass$innerClass.

ex20:
  在一个包含嵌套(静态内部)类的类的方法中,可以只引用嵌套类名定义嵌套(静态内部)类,但在该类外,必须指定外部类和嵌套类。

ex21
  注意,我们使用一个匿名内部类来实现接口I.这样往往能更清晰地列出接口的所有方法,然后定义嵌套类。

0 0
原创粉丝点击