成员内部类与方法内部类
成员内部类
成员内部类类似于类的成员,例如变量或方法。它能够访问外部类的所有变量和方法。
public class OuterClass {
    private int x = 10;
    class InnerClass {
        public void print() {
            System.out.println(x);  // 访问外部类的变量
        }
    }
    public void createInner() {
        InnerClass inner = new InnerClass();
        inner.print();  // 创建内部类实例并调用其方法
    }
}
在上述示例中,InnerClass 作为 OuterClass 的成员,能够直接访问外部类的私有变量 x。通过 createInner 方法,可以实例化内部类并调用其方法。
方法内部类
方法内部类是在方法内部定义的类。它只能在定义它的方法内部被访问和使用。
方法内部类有以下特点:
- 编译后的文件名为
外部类名$内部类名.class。 - 方法内部类可以访问定义它的方法中的局部变量。
 - 必须在方法内部实例化,并调用相应的方法。
 - 使用方法内部类时,方法的局部变量必须具有 
final特性。- 在 Java 8 之前,必须显式使用 
final关键字修饰。 - 在 Java 8 及之后,即使未显式声明 
final,只要不修改该变量,编译器也会将其视为final。 
 - 在 Java 8 之前,必须显式使用 
 
public class OuterClass {
    void outerMethod() {
        int number = 100; // 这个变量是 effectively final 的,因为没有被修改
        // 局部内部类
        class InnerClass {
            void printNumber() {
                System.out.println("Number is " + number);
            }
        }
        // 创建局部内部类的实例并调用方法
        InnerClass inner = new InnerClass();
        inner.printNumber();
    }
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.outerMethod();
    }
}
在这个例子中,InnerClass 定义在 outerMethod 方法内部,并且可以访问方法中的局部变量 number。由于 number 没有被修改,它被视为 effectively final,因此可以在内部类中使用。
静态内部类
静态内部类只能访问外部类的静态成员。
静态内部类的优势包括:
- 不依赖于外部类的实例,避免了外部类实例被垃圾回收时内部类实例的内存泄漏。
 - 可以直接实例化静态内部类,而无需依赖外部类的实例。
 - 命名空间更为清晰,语义化更完整,例如 
DBManager.DBConnect.test()。 - 适用于定义外部类中的工具类或辅助类。
 
public class OuterClass {
    private static String staticMessage = "Hello, World!";
    private String nonStaticMessage = "Hello, Java!";
    public static class StaticNestedClass {
        public void printMessage() {
            System.out.println(staticMessage); // 访问外部类的静态成员
            // System.out.println(nonStaticMessage); // 错误,无法访问外部类的非静态成员
        }
    }
}
在这个示例中,StaticNestedClass 是一个静态内部类,它只能访问 OuterClass 的静态成员 staticMessage。尝试访问非静态成员 nonStaticMessage 会导致编译错误。
匿名内部类
匿名内部类是在需要实现某个接口或继承某个类时,不需要为该实现创建一个完整的类而使用的一种内部类。它们可以使代码更加简洁,并且可以在定义它们的地方立即看到它们的实现。
接口匿名内部类
当需要实现一个接口但不需要为其创建单独的类时,可以使用接口匿名内部类。
interface Greeting {
    void greet();
}
public class Main {
    public void sayHello() {
        Greeting englishGreeting = new Greeting() {
            @Override
            public void greet() {
                System.out.println("Hello, world!");
            }
        };
        englishGreeting.greet();
    }
    public static void main(String[] args) {
        new Main().sayHello();
    }
}
在这个例子中,Greeting 接口通过匿名内部类得到了实现,sayHello 方法中创建了该实现的实例并调用了 greet 方法。
抽象方法匿名内部类
当需要使用一个抽象类,并且只需使用一次该类时,可以选择使用匿名内部类。
abstract class AbstractDisplay {
    abstract void display();
}
public class Main {
    public static void main(String[] args) {
        AbstractDisplay display = new AbstractDisplay() {
            @Override
            void display() {
                System.out.println("Displaying abstract class method");
            }
        };
        display.display();
    }
}
在这个示例中,AbstractDisplay 是一个抽象类,通过匿名内部类进行了实现,并在 main 方法中调用了 display 方法。
参数匿名内部类
当需要将一个类的实例作为方法参数传递,而这个类可能在其他地方不会被使用时,可以使用参数匿名内部类。
public class Main {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("New thread created");
            }
        }).start();
    }
}
在这个例子中,Runnable 接口通过匿名内部类得到了实现,并作为参数传递给 Thread 的构造方法。这种方式使得代码更加简洁,且无需为 Runnable 接口创建一个单独的实现类。