首页 > 代码库 > 《Java开发手册》学习进程之第15章内部类

《Java开发手册》学习进程之第15章内部类

非静态内部类:

从非静态内部类外面看,完全可以将其看成是外部类的一个非静态成员,与普通的成员没有什么区别。只是这个成员不再是基本数据类型,也不再是对象引用,而是一个类,由一个类来扮演成员的角色。

内部类的访问限制修饰符除了外部类的public和默认外,还可以添加private和protected。

虽然内部类位于外部类的类体中,但编译后内部类与外部类各自产生一个类文件。

因为非静态内部类扮演的是外部类非静态成员的角色,而非静态成员只有在所属对象存在的情况下才存在,因此非静态内部类在创建了外部类对象后才可以使用。

内部类与外部类之间的成员互访:

对于外部类来说,内部类也是其中一个成员,所以在内部类中使用外部类的成员时,就相当于普通成员之间的互相访问,如同一个类中不同方法间的相互调用。因此,在内部类中可以访问外部类的任何成员,即使是private的。

如果在外部类中访问内部类的非静态成员,需要首先创建内部类的对象。即使是内部类的私有成员,外部类一样可以访问。

非静态内部类不能有静态成员。在Java的装载过程,先加载类,然后初始化静态的东西,并且Java编译器必须保证所有的静态都在使用前分配好内存空间,然后非静态的只有在使用的时候才分配内存空间。 所以非静态的InnerClass必须得要OutClass实例化之后才会存在,所以非静态InnerClass的静态成员在开始的时候并没有得到初始化(因为这些内存是无法通过任何方式访问的),这就和JAVA的编译原则相违背了。

预定义对象引用this:

预定义对象引用this是指向当前对象自身的引用,但当内部类对象与外部类对象有同名的成员变量时,只使用this无法从内部类中访问外部类的同名成员变量,因为此时this指内部类对象自身。

如果在内部类中需要使用外部类对象的this,则可以使用如下语法:

<外部类名>.this.<外部类中需要被访问的成员名>

局部内部类:

当内部类扮演的是“局部”的角色时,其作用域与局部变量相同,只在其所在的语句块中有效。

局部内部类中一样可以访问外部类的成员,但却不可以访问同在一个局部的普通局部变量(而final的则可以):

  • 普通的局部变量随着所在语句块的执行结束而消亡,而创建的局部内部类对象并不会随着语句块的结束而消亡。如果在语句块结束后,调用了局部内部类对象中访问普通局部变量的方法就要出现问题,因为此时要访问的局部变量已经不存在了。
  • final的局部变量存储方式与普通局部变量不同,其不会因为语句块的结束而消失,还会长期存在。

如果局部内部类位于静态方法中,则只能访问外部类静态的成员,这与静态方法访问成员的规则一致。

静态内部类:

因为静态内部类是外部类的静态成员,因此其不能直接访问外部类的非静态成员。

静态和非静态内部类的区别:

非静态内部类应该与外部类的对象存在着对成员的共享关系,其是外部类对象组成的一部分,是用来辅助外部类对象工作的。

静态内部类其实已经脱离了外部类的控制,在创建其对象时已经不再需要外部类对象的存在了,实质上只是一个文墨在别的类中的普通类而已。

匿名内部类:

匿名内部类没有名称,因此匿名内部类在声明类的同时也创建了其对象。匿名内部类的声明要么是基于继承的,要么是基于实现接口的。

在匿名内部类类体中可以重写父类的方法,或提供自己新的方法与成员。但要注意的是,因为匿名内部类没有名字,所以没有办法声明匿名内部类类型的引用,因此提供的新的方法与成员只能自己内部使用,外面无法使用。

一般对匿名内部类对象的使用都是通过多态进行的,用其继承的直接或间接父类的引用指向该对象。因此通过引用只能调用其重写的父类方法,其自己的方法与成员无法调用。

在基于接口实现的匿名内部类中,因为其没有名称,无法被继承,固其不能是抽象的,因此在类体中必须实现接口中所有的方法。

在匿名内部类中要初始化父类的成员变量需要用到非静态语句块。

匿名内部类的作用体现:

在特定情况下,匿名内部类可以减少冗余的代码。因为在实际开发中,有很多自己编写的类只需要使用一次,并不需要多次创建对象,这时使用匿名内部类将类代码与创建对象同步完成。

内部接口:

扮演成员角色的接口一般被称为内部接口。

定义在类中的内部接口:

定义在类中的内部接口扮演的是外部成员的角色,在使用时需要注意以下几点:

  • 内部接口无论是否使用static修饰,扮演的都是静态成员。
  • 同成员内部类一样,内部接口作为外部类的一个成员,需要满足成员的所有规则,具有成员的所有能力。例如,内部接口也可以被成员访问限制修饰符进行修饰,而普通接口不行。
  • 当使用private访问限制修饰符修饰内部接口时,意味着该接口只能由其外部类中的某个内部类来实现。
  • 内部接口不能扮演局部的角色。

《Java开发手册》学习进程之第15章内部类