内部类的知识点较多,我看了好几篇文章,想系统的总结一下。
内部类分为:静态内部类,成员内部类,方法内部类,匿名内部类
静态内部类是定义在另一个类里面用 static 修饰 class 的类,静态内部类不需要依赖于外部类(与类的静态成员属性类似)且无法使用其外部类的非 static 属性或方法(因为在没有外部类对象的情况下可以直接创建静态内部类的对象,如果允许访问外部类的非 static 属性或者方法就会产生矛盾)。
成员内部类是没有用 static 修饰且定义在在外部类类体中的类,是最普通的内部类,可以看做是外部类的成员,可以无条件访问外部类的所有成员属性和成员方法(包括 private 成员和静态成员),而外部类无法直接访问成员内部类的成员和属性,要想访问必须得先创建一个成员内部类的对象然后通过指向这个对象的引用来访问;当成员内部类拥有和外部类同名的成员变量或者方法时会发生隐藏现象(即默认情况下访问的是成员内部类的成员,如果要访问外部类的同名成员需要通过 OutClass.this.XXX 形式访问);成员内部类的 class 前面可以有 private 等修饰符存在。
public class OutClass {
public class InnerClass {
}
}
编译OutClass.java会得到两个class文件,分别是OutClass.class和OutClassInnerClass.class,通过javap OutClassInnerClass.java可以看到编译后:
Compiled from "OutClass.java"
public class OutClass$InnerClass.java {
final Object this$0;
public OutClass$InnerClass(OutClass);
}
可以看到有一个指向外部类的引用,并且构造函数对其赋值,所以在成员内部类中可以随意访问外部类成员或方法
class OutClass {
class InnerClass {
}
}
// 成员内部类子类定义标准
class ChildInnerClass extends OutClass.InnerClass {
public ChildInnerClass(OutClass) {
outClass.super();
}
}
方法内部类(局部内部类)是定义在一个方法里面的类,和成员内部类的区别在于方法内部类的访问仅限于方法内;方法内部类就像是方法里面的一个局部变量一样,所以其类 class 前面是不能有 public、protected、private、static 修饰符的,也不可以在此方法外对其实例化使用。
匿名内部类是一种没有构造器的类(实质是继承类或实现接口的子类匿名对象),由于没有构造器所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调,匿名内部类在编译的时候由系统自动起名为 OutClass$1.class,一般匿名内部类用于继承其他类或实现接口且不需要增加额外方法的场景(只是对继承方法的实现或是重写);匿名内部类的 class 前面不能有 pravite 等修饰符和 static 修饰符;匿名内部类访问外部类的成员属性时外部类的成员属性需要添加 final 修饰(1.8 开始可以不用)
使用匿名内部类时必须是继承一个类或实现一个接口(二者不可兼得且只能继承一个类或者实现一个接口)
匿名内部类中是不能定义构造函数的,如需初始化可以通过构造代码块处理
匿名内部类中不能存在任何的静态成员变量和静态方法
匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效
匿名内部类不能是抽象类,必须要实现继承的类或者实现接口的所有抽象方法