概念分类
成员内部类:成员内部类是最普通的内部类,可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
局部内部类:局部内部类是定义在一个方法、构造器或代码块中的类。它只能在其定义的范围内使用,通常用于封装仅在该方法中需要的逻辑。
静态内部类:静态内部类不持有外部类的引用,可直接通过外部类名访问,不需要外部类的实例即可创建。
匿名内部类:匿名内部类通常用于单次使用的类,如事件监听器等场景。
访问权限
成员内部类:成员内部类可以访问外部类的所有成员,包括私有成员。
局部内部类:局部内部类只能访问外部类的final变量或者实际上不变的变量。(Java8以上可以,但是不推荐)
静态内部类:静态内部类无法访问外部类的非静态成员。
匿名内部类:匿名内部类通常用于重写某个或某些方法的场景。
实例化方式
成员内部类:成员内部类必须先实例化外部类,然后使用外部类的实例来实例化内部类。
局部内部类:局部内部类的对象的创建时机是在方法调用时,随方法执行完毕而销毁。
静态内部类:静态内部类可以直接实例化,无需外部类实例。
匿名内部类:匿名内部类在使用时直接通过new关键字后跟接口或类名进行实例化。
应用场景
成员内部类:成员内部类适用于与外部类关系紧密,共同完成特定功能的场景。
局部内部类:局部内部类适用于在特定方法内实现功能,且不希望在外部类其他部分可见的场景。
静态内部类:静态内部类适用于内部类的功能与外部类实例无关,只需访问静态成员的场景。
匿名内部类:匿名内部类适用于实现接口或继承类的场合,特别是只需要一次实现的情况。
成员内部类
public class scratch_7 {
public static void main(String[] args) {
OutClass outClass = new OutClass();
OutClass.InnerClass innerClass = outClass.new InnerClass();
innerClass.printFields();
}
}
class OutClass {
private String outerField = "Outer Field";
public static String outerStaticField = "Outer Static Field";
// 成员内部类
class InnerClass {
private String innerField = "Inner Field";
// public static String innerStaticField = "Inner Static Field";
public final static String innerFinalField = "Inner Final Field";
public void printFields() {
System.out.println("Outer Field: " + outerField);
System.out.println("Outer Static Field: " + outerStaticField);
System.out.println("Inner Field: " + innerField);
System.out.println("Inner Final Field: " + innerFinalField);
// System.out.println("Inner Static Field: " + innerStaticField);
}
}
}
输出
Outer Field: Outer Field
Outer Static Field: Outer Static Field
Inner Field: Inner Field
Inner Final Field: Inner Final Field
innerStaticField是不被允许的:对于非静态内部类来说,它的存在依赖于外部类的实例。在创建外部类的实例之前,内部类本身并没有被加载到内存中,因此如果内部类中包含静态成员,就会出现矛盾:静态成员需要在外部类实例化后才能将内部类加载,但那时外部类还没有实例化,也就无法加载内部类。
innerFinalField是被允许的:如果将成员内部类中的静态变量声明为final,并且赋予一个编译时已知的常量值(如字面量),则编译不会出错。这是因为final static变量实际上是编译时常量,它们在编译时就被替换,不需要在运行时再进行初始化
局部内部类
public class scratch_7 {
public static void main(String[] args) {
OutClass outClass = new OutClass();
OutClass.InnerClass innerClass = outClass.new InnerClass();
innerClass.printFields();
}
}
class OutClass {
private String outerField = "Outer Field";
public static String outerStaticField = "Outer Static Field";
// 成员内部类
class InnerClass {
private String innerField = "Inner Field";
public final static String innerFinalField = "Inner Final Field";
public void printFields() {
int innerMethodField = 40;
class InnerInnerClass {
public void printFields() {
System.out.println("outerField: " + outerField);
System.out.println("outerStaticField: " + outerStaticField);
System.out.println("innerField: " + innerField);
System.out.println("innerFinalField: " + innerFinalField);
System.out.println("innerMethodField: " + innerMethodField);
}
}
InnerInnerClass innerInnerClass = new InnerInnerClass();
innerInnerClass.printFields();
}
}
}
结果
outerField: Outer Field
outerStaticField: Outer Static Field
innerField: Inner Field
innerFinalField: Inner Final Field
innerMethodField: 40
静态内部类
public class scratch_7 {
public static void main(String[] args) {
OutClass.InnerClass.printFields();
}
}
class OutClass {
public static String outerStaticField = "Outer Static Field";
// 成员内部类
static class InnerClass {
public static String innerField = "Inner Final Field";
public String innerField2 = "innerField2";
public static void printFields() {
int innerMethodField = 40;
class InnerInnerClass {
public void printFields() {
System.out.println("outerStaticField: " + outerStaticField);
System.out.println("innerFinalField: " + innerField);
System.out.println("innerMethodField: " + innerMethodField);
// System.out.println("innerMethodField: " + innerField2);
}
}
InnerInnerClass innerInnerClass = new InnerInnerClass();
innerInnerClass.printFields();
}
}
}
结果
outerStaticField: Outer Static Field
innerFinalField: Inner Final Field
innerMethodField: 40
Inner Final Field
匿名内部类
public class scratch_7 {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.printFields();
}
}
class OutClass {
public static String outerStaticField = "Outer Static Field";
public void printFields() {
InnerClass innerClass = new InnerClass() {
@Override
public void printFields() {
System.out.println("printFields");
}
};
innerClass.printFields();
}
interface InnerClass {
void printFields();
}
}
简化为使用lambda表达式
public class scratch_7 {
public static void main(String[] args) {
OutClass outClass = new OutClass();
outClass.printFields();
}
}
class OutClass {
public static String outerStaticField = "Outer Static Field";
public void printFields() {
Runnable runnable = () -> {
System.out.println("printFields");
};
runnable.run();
}
}
Runnable只能实现单一无返回值方法,如果需要返回值可以使用Callable