在Java中,内部类是定义在另一个类或者其他类的方法中的类。内部类提供了一种实现细节隐藏和封装的机制,同时也可以在需要时访问外部类的成员变量和方法。Java中有四种类型的内部类:成员内部类、局部内部类、匿名内部类和静态嵌套类。下面详细介绍这些内部类:
1.成员内部类(Member Inner Class)
成员内部类是定义在另一个类的内部的普通类。它可以访问外部类的成员变量和方法,并且可以拥有自己的成员变量和方法。成员内部类的实例化需要先创建外部类的实例,然后通过外部类实例来创建成员内部类的实例。
public class Outer {
private int outerField;
public class Inner {
public void display() {
System.out.println("Outer Field: " + outerField);
}
}
}
示例:比如一个图书馆系统中的书架和书籍。
// 外部类:图书馆 public class Library { private String libraryName; // 构造方法 public Library(String name) { this.libraryName = name; } // 成员内部类:书架 public class Bookshelf { private int capacity; // 构造方法 public Bookshelf(int capacity) { this.capacity = capacity; } // 内部类的方法 public void displayBookshelfInfo() { System.out.println("Bookshelf capacity: " + capacity); System.out.println("Library name: " + libraryName); } } // 外部类的方法 public void displayLibraryInfo() { System.out.println("Library name: " + libraryName); } }
在这个示例中,
Library
类表示一个图书馆,它有一个成员变量libraryName
表示图书馆的名字。Library
类内部还定义了一个成员内部类Bookshelf
,表示图书馆中的书架。Bookshelf
类有一个成员变量capacity
表示书架的容量。Bookshelf
类的构造方法中通过访问外部类的成员变量libraryName
,显示了所属图书馆的名字。同时,Library
类中还有一个方法displayLibraryInfo()
,用于显示图书馆的信息。接下来是如何使用这些类的示例代码:
public class Main { public static void main(String[] args) { // 创建图书馆实例 Library library = new Library("City Library"); // 创建书架实例 Library.Bookshelf bookshelf = library.new Bookshelf(100); // 调用书架的方法显示信息 bookshelf.displayBookshelfInfo(); // 调用图书馆的方法显示信息 library.displayLibraryInfo(); } }
在这个示例中,我们首先创建了一个图书馆实例
library
,然后通过该实例创建了一个书架实例bookshelf
。接着,调用了书架实例的displayBookshelfInfo()
方法显示了书架的信息,以及图书馆的displayLibraryInfo()
方法显示了图书馆的信息。这个示例展示了成员内部类的使用,其中成员内部类
Bookshelf
可以轻松访问外部类Library
的成员变量libraryName
,并且可以在其内部定义自己的成员变量和方法。
2.局部内部类(Local Inner Class)
局部内部类是定义在方法内部的类。它只能在该方法中被访问,通常用于解决一个方法内部的问题。与成员内部类不同,局部内部类不能被访问修饰符 private
、public
、protected
和 static
修饰。
public class Outer {
public void display() {
class LocalInner {
public void print() {
System.out.println("Local Inner");
}
}
LocalInner inner = new LocalInner();
inner.print();
}
}
示例:在一个 GUI 应用程序中,当用户点击一个按钮时,可能需要执行一些特定的操作。如果这个操作是一个比较简单的逻辑,而且只在按钮的点击事件中使用,那么可以使用局部内部类来实现这个事件监听器。
import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class ButtonExample { public static void main(String[] args) { // 创建 JFrame 实例 JFrame frame = new JFrame("Button Example"); // 创建按钮 JButton button = new JButton("Click Me"); // 添加按钮点击事件监听器 button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("Button clicked!"); JOptionPane.showMessageDialog(frame, "Button clicked!"); } }); // 将按钮添加到 JFrame 中 frame.add(button); // 设置 JFrame 的大小和关闭操作 frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
在这个示例中,我们创建了一个简单的 GUI 应用程序,其中包含一个按钮。我们通过调用
addActionListener
方法来添加一个按钮点击事件的监听器。在这个方法中,我们传入了一个匿名内部类作为监听器,该内部类实现了ActionListener
接口,并在actionPerformed
方法中定义了按钮点击时所需执行的逻辑。在这个例子中,当按钮被点击时,会在控制台打印消息,并弹出一个消息对话框显示相同的消息。
3.匿名内部类(Anonymous Inner Class)
匿名内部类是一种没有命名的内部类,通常用于创建一个只需使用一次的类。它通常是一个接口或者抽象类的实现,并且在创建对象时直接进行定义。
-
没有名称:匿名类没有类名,因此它们不能被其他代码引用或重复使用。
-
直接创建:匿名类通常是在使用的地方直接创建的,例如作为方法参数、变量初始化或者数组初始化的一部分。
-
实现接口或抽象类:匿名类通常用于实现接口或抽象类,但也可以扩展类并提供自己的方法实现。
public class Outer {
public void display() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Anonymous Inner");
}
};
new Thread(runnable).start();
}
}
以下是一个简单的示例,演示了如何使用匿名内部类来实现接口:
interface Greeting { void greet(); } public class AnonymousInnerClassExample { public static void main(String[] args) { // 使用匿名内部类实现接口 Greeting greeting = new Greeting() { @Override public void greet() { System.out.println("Hello, world!"); } }; // 调用接口方法 greeting.greet(); } }
在这个示例中,我们定义了一个接口
Greeting
,其中有一个抽象方法greet
。然后,在main
方法中,我们创建了一个匿名内部类实现了这个接口,并在其中重写了greet
方法。在匿名内部类的定义中,我们没有指定类名,而是直接创建了一个实现了Greeting
接口的类,并重写了其中的方法。最后,我们通过接口的引用调用了greet
方法,输出了 "Hello, world!"。
4.静态嵌套类(Static Nested Class)
静态嵌套类是定义在另一个类的内部的静态类。与其他内部类不同,静态嵌套类不持有外部类的引用,因此它不能访问外部类的非静态成员。可以直接通过外部类名访问静态嵌套类。
public class Outer {
static class Nested {
public void display() {
System.out.println("Static Nested");
}
}
}
以下是一个静态嵌套类的示例:
public class Outer { private static String outerField = "Outer field"; // 静态嵌套类 static class Nested { public void display() { System.out.println("Nested class accessing Outer field: " + outerField); } } public static void main(String[] args) { // 创建静态嵌套类的实例 Nested nested = new Nested(); nested.display(); } }
在这个示例中,
Outer
类包含了一个静态嵌套类Nested
。Nested
类具有一个display
方法,该方法打印了外部类Outer
的静态字段outerField
的值。在main
方法中,我们创建了Nested
类的实例,并调用了display
方法来访问外部类的静态字段。