转载请注明出处:https://www.cnblogs.com/zhizaixingzou/p/10023862.html
目录
1. 内部类
1.1. 概念
定义在另一个类里的类叫内部类,包含内部类的类即它的外部类。
1.2. 4种内部类
1.2.1. 成员内部类
之所以叫成员内部类,是因为它定义的位置和被访问的方式与其他成员一样:成员内部类可以无条件访问外部类的所有成员(内部类隐含着一个“外部类.this”,就像普通类自己内含this一样,这个无条件访问就是通过“外部类.this”达成的),就像普通类的成员方法可以无条件访问它自己的所有成员一样。
在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问。
内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限,就像其他成员可以有这些可访问性一样。
当成员内部类拥有和外部类同名的成员变量或者方法时,默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象。
1.2.2. 局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
1.2.3. 匿名内部类
一般来说,匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。
1.2.4. 静态内部类
静态内部类像成员内部类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很像类的静态方法。
1.3. 成员内部类访问外部类成员的原理
假设外部类为Outter,内部类为Inner,编译器会产生两个字节码文件Outter.class和Outter$Inner.class。
编译器为内部类添加了一个外部类字段,该字段通过构造方法传入一个参数初始化,该参数也是编译器额外做的。这也说明了内部类依赖于外部类的实例的创建。
匿名内部类和局部内部类也有这个过程,也可以访问外部类成员。
1.4. 为何匿名内部类和局部内部类只能访问final变量
默认情况下,编译器会为匿名内部类和局部内部类起名为:外部类$x.class(x为正整数)。
当test方法执行完毕之后,变量a的生命周期就结束了,而此时Thread对象的生命周期很可能还没有结束,那么在Thread的run方法中继续访问变量a就变成不可能了,但是又要实现这样的效果,怎么办呢?Java采用了复制的手段来解决这个问题。
如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。如果局部变量的值无法在编译期间确定,则为内部类创建字段,通过构造器传参的方式来对该字段拷贝进行初始化赋值。
也就是说,外部方法中的变量与内部类访问的变量已经不是同一个了,为了防止数据不一致,如中途改变对象所指,所以内部类访问的外部方法的局部变量必须是final的。
1.5. 内部类的继承
1.6. 使用内部类的好处
1.每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整,
2.方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
3.方便编写事件驱动程序
4.方便编写线程代码