内部类

1. 成员内部类

1.1. 实例内部类

  1. 创建实力内部类的实例时.外部类的实例必须已经存在.

  2. 实例内部类的实例自动持有外部类的实例的引用.可以访问外部类的所有成员变量和方法.多重嵌套中,内部类可以访问所有外部类的成员.

  3. 在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问.

  4. 实例内部类不能定义静态成员.

  5. 如果实力内部类B与外部类A包含同名的成员(如变量v),那么在类B中,this.v表示类B的成员, A.this.v表示类A的实例成员,A.v表示类A的静态成员

1.2. 静态内部类

  1. 静态内部类的实例不会自动持有外部类的特定实例的引用.创建外内部类实例时可以不必创建外部类实例.如:new A.B();

  2. 静态内部类可以直接访问外部类的静态成员,访问外部类的实例成员需通过外部类的实例去访问

  3. 静态内部类中可以定义静态成员和实例成员

  4. 可以通过A.B.v2直接访问静态内部类B的静态成员变量v2,不能通过A.B.v1访问静态内部类的实例变量v1.

2. 局部内部类(方法内部类)

  1. 局部内部类及其内部类不能被public,private,protected和static修饰

  2. 局部内部类只能在当前方法中使用.

  3. 局部内部类不能包含静态成员

  4. 局部内部类可以访问外部类的所有成员.可以访问所在方法的final类型变量和参数,不能访问非final修饰的变量和参数(原因:局部变量的生命周期与局部内部类的对象的生命周期的不一致性!解决办法:通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员,通过构造方法注入)

3. 匿名类

  1. 匿名类本身没有构造方法,但会调用父类的构造方法。如new A(v){},若参数v是局部变量,则v必须为final类型

  2. 匿名类可以通过写构造代码块来实现自定义的初始化。

  3. 匿名类除了定义在方法内外还可以用在成员变量的显示初始化上。

  4. 匿名类除了可以继承类还可以实现接口

  5. 匿名类和局部内部类一样可以访问外部类的所有成员和方法内的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开始的正整数后跟局部类名-其中数字部分是局部类在外部类上下文出现的先后顺序

results matching ""

    No results matching ""