内部类
1. 成员内部类
1.1. 实例内部类
创建实力内部类的实例时.外部类的实例必须已经存在.
实例内部类的实例自动持有外部类的实例的引用.可以访问外部类的所有成员变量和方法.多重嵌套中,内部类可以访问所有外部类的成员.
在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问.
实例内部类不能定义静态成员.
如果实力内部类B与外部类A包含同名的成员(如变量v),那么在类B中,this.v表示类B的成员, A.this.v表示类A的实例成员,A.v表示类A的静态成员
1.2. 静态内部类
静态内部类的实例不会自动持有外部类的特定实例的引用.创建外内部类实例时可以不必创建外部类实例.如:new A.B();
静态内部类可以直接访问外部类的静态成员,访问外部类的实例成员需通过外部类的实例去访问
静态内部类中可以定义静态成员和实例成员
可以通过A.B.v2直接访问静态内部类B的静态成员变量v2,不能通过A.B.v1访问静态内部类的实例变量v1.
2. 局部内部类(方法内部类)
局部内部类及其内部类不能被public,private,protected和static修饰
局部内部类只能在当前方法中使用.
局部内部类不能包含静态成员
局部内部类可以访问外部类的所有成员.可以访问所在方法的final类型变量和参数,不能访问非final修饰的变量和参数(原因:局部变量的生命周期与局部内部类的对象的生命周期的不一致性!解决办法:通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员,通过构造方法注入)
3. 匿名类
匿名类本身没有构造方法,但会调用父类的构造方法。如new A(v){},若参数v是局部变量,则v必须为final类型
匿名类可以通过写构造代码块来实现自定义的初始化。
匿名类除了定义在方法内外还可以用在成员变量的显示初始化上。
匿名类除了可以继承类还可以实现接口
匿名类和局部内部类一样可以访问外部类的所有成员和方法内的final变量和参数。
4. 内部类的特性
不允许内部类与外部类重名
4.1. 内部类的继承
public class Sample extends Outer.Inner{
public Sample(Outer o){
o.super;
}
}
因为构建一个内部类的实例需要外部类的实例,所以,Sample继承Inner类时需在构造时传入一个Outer实例的引用,o.super()指的是执行o的inner内部类的构造方法.
4.2. 子父类的内部类同名
和子父类的同名成员变量一样,子父类的同名内部类都是独立的,互相不影响.java编译器不会检查子类中的Inner类是否缩小了父类中的Inner类的访问权限.
4.3. 内部接口
一个类中可以定义内部接口(静态非静态都可以)。
4.4. 接口的静态内部类
接口中可以定义静态内部类,实现了接口的类对内部类可见(可直接调用)
非实现类必须通过接口.内部类来调用。
5. 命名规则
内部类的class文件命名是:包名.外部类名$内部类名
匿名类的class文件命名是:包名.外部类名$由1开始的正整数-按照类装载顺序依次排列
局部内部类class文件命名是:包名.外部类名$由1开始的正整数后跟局部类名-其中数字部分是局部类在外部类上下文出现的先后顺序