1、非静态内部类
非静态内部类,也就是成员内部类,是定义在另一个类内部的非静态类。这种内部类与外部类之间有着密切的联系,它可以访问外部类的所有成员(包括私有成员),同时外部类也可以访问内部类的所有成员(包括私有成员)。
public class Main { private int outerValue = 100; public static void main(String[] args) { Main outer = new Main(); Main.InnerClass inner = outer.new InnerClass(); inner.display(); System.exit(0); //success } class InnerClass { private int innerValue = 200; public void display() { System.out.println("Outer Value: " + outerValue); // 访问外部类成员 System.out.println("Inner Value: " + innerValue); // 访问内部类成员 } } }
注意:同一个java源文件定义了多个类,它们之间是相互独立的,那种情况不是内部类。
2、静态内部类
Java中的静态内部类(Static Nested Class)是定义在另一个类内部的静态类。由于是静态的,这种内部类与外部类的实例无关,并且不能直接访问外部类的非静态成员和方法。可以访问外部类的静态成员,包括私有的静态成员。静态内部类的独立性使其成为实现与外部类相关但又可独立存在。静态内部类在Java中的应用场景包括逻辑分组(将相关的类组织在一起),封装(隐藏内部类的细节,保持外部类的清洁接口),以及减少内存占用(静态内部类不持有对外部类实例的引用)。它们在设计模式中也很有用。
public class Main { private static String staticVar = "外部静态变量"; static class StaticNestedClass { public void display() { System.out.println("访问 outer class static variable: " + staticVar); } } public static void main(String[] args) { Main.StaticNestedClass nestedObject = new Main.StaticNestedClass(); nestedObject.display(); } }
3、局部内部类
局部内部类(Local Inner Class)是定义在一个方法或任意作用域内的类。它对于实现复杂的逻辑非常有用,尤其是当这些逻辑仅在定义它的块内部需要时。局部内部类对外部完全隐藏,只能在定义它的作用域内被使用。局部内部类可以访问其外围方法的局部变量(Java 8之后,即使这些变量不是final的也可以访问)和外部类的所有成员。这些类不能有静态成员,因为它们与外部世界隔离。局部内部类主要用于实现那些仅在某个方法或作用域内使用的类,以及在需要实现或继承特定接口或类且其使用非常局限的情况下。
public class Main { public static void main(String[] args) { Main outer = new Main(); outer.display(); } public void display() { // 局部内部类在方法内定义 class LocalInnerClass { public void print() { System.out.println("局部内部类"); } } // 局部内部类的对象创建和使用 LocalInnerClass localInnerClass = new LocalInnerClass(); localInnerClass.print(); } }
4、匿名内部类
匿名内部类是一种没有名称的局部内部类。它们通常用于实现接口或继承某个类的同时,创建并实例化一个对象。匿名内部类对于编写事件监听器、实现回调等场景特别有用。匿名内部类是一种特殊的内部类,它没有具体的类名。这种类通常用于一次性使用的场景,如实现接口或继承某个类时。由于匿名内部类没有名称,因此在定义的同时会立即创建一个对象实例。这种类的主要优点是语法简洁,使代码更加清晰和简洁,尤其适用于事件处理(例如GUI编程中的事件监听器)和在方法调用中实现接口的情况。
匿名内部类可以访问外部类的所有成员,包括私有成员,以及定义它的方法内的final或effectively final局部变量。然而,匿名内部类不能定义静态成员、方法或类,并且由于缺乏具体的类名,它们也不能有构造方法。
public class Main { public static void main(String[] args) { // 使用匿名内部类实现Runnable接口 Runnable r = new Runnable() { public void run() { System.out.println("匿名内部类的run方法"); } }; new Thread(r).start(); } }
5、闭包和回调
闭包是一种编程概念,指的是一个函数及其引用的外部环境的组合。在Java中,闭包通常通过内部类实现。由于内部类可以访问其外部类的成员变量和方法,这使得它可以捕获并持有这些外部变量的状态,从而形成闭包。
public class Main { public static void main(String[] args) { new Thread(new Main().createClosure()).start(); } private int outerField = 100; public Runnable createClosure() { class Inner implements Runnable { public void run() { System.out.println(outerField); } } return new Inner(); } }
回调是一种常见的编程模式,用于异步或事件驱动编程。回调通常是作为一个函数传递到另一个函数中,当特定事件或条件发生时,这个传递的函数被调用。在Java中,回调经常通过使用接口或抽象类以及内部类来实现。
public class Main { public static void main(String[] args) { EventHandler eventHandler = new EventHandler(new Callback() { @Override public void onEvent() { System.out.println("Callback triggered!"); } }); eventHandler.doSomething(); } } interface Callback { void onEvent(); } class EventHandler { private Callback callback; public EventHandler(Callback callback) { this.callback = callback; } public void doSomething() { // 事件处理... callback.onEvent(); // 触发回调 } }