内部类是定义在另一个类内部的类。它们与外部类之间存在一种特殊的关系,内部类可以访问外部类的成员,包括私有成员,而外部类也可以访问内部类的成员。内部类提供了一种封装和组织代码的方式,并且可以用于实现一些特定的设计模式和功能。
Java中有四种类型的内部类:
成员内部类(Member Inner Class)
成员内部类是定义在类内部的普通类,它与外部类的实例相关联
。成员内部类可以访问外部类的成员,包括私有成员,并且可以使用this
关键字来引用外部类的实例。可以通过以下语法创建成员内部类的实例:
public class OuterClass {
/**
* 静态内部类
**/
static class InnerClass {
private String name;
private Integer age;
@Override
public String toString() {
return "InnerClass{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) {
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
innerClass.name="wangzijian";
innerClass.age=18;
System.out.println(innerClass);
}
}
静态内部类(Static Inner Class)
静态内部类是定义在类内部的静态类,它与外部类的实例无关
,并且可以直接通过外部类的类名访问。静态内部类不能访问外部类的非静态成员,只能访问外部类的静态成员。可以通过以下语法创建静态内部类的实例:
public class OuterClass {
/**
* 成员内部类
*/
class InnerClass {
private String name;
private Integer age;
@Override
public String toString() {
return "InnerClass{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.name = "wangzijian";
innerClass.age = 18;
System.out.println(innerClass);
}
}
局部内部类(Local Inner Class)
局部内部类是定义在方法或作用域内的类,它的作用域被限定在所在的方法或作用域中
。局部内部类可以访问外部类和方法或作用域的局部变量,但这些变量必须是final
或实际上的final
(Java 8+中允许访问非final
的局部变量)。局部内部类的作用域仅限于定义它的方法或作用域内部。
public class OuterClass {
public static void fun() {
/**
* 方法内部类
**/
class InnerClass {
private String name;
private Integer age;
@Override
public String toString() {
return "InnerClass{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
InnerClass innerClass = new InnerClass();
innerClass.name = "wangzijian";
innerClass.age = 18;
System.out.println(innerClass);
}
public static void main(String[] args) {
fun();
}
}
匿名内部类(Anonymous Inner Class)
匿名内部类是没有显式定义类的名称
的内部类,它通常用于创建只需要一次使用的简单类。匿名内部类可以实现接口或扩展类,并且可以在创建对象的同时进行方法重写或实现。匿名内部类不能有显式的构造函数
。
public interface Person {
/**
* 人说话
*
* @param name
*/
void speak(String name);
}
public class OuterClass {
public static void main(String[] args) {
Person person = new Person() {
@Override
public void speak(String name) {
System.out.println(name);
}
};
person.speak("hello world!");
}
}
内部类的使用场景和优势:
-
封装性:内部类可以访问外部类的私有成员,可以在内部类中隐藏一些细节,提高代码的封装性和安全性。
-
实现特定功能:内部类可以用于实现一些特定的功能和设计模式,例如迭代器模式、事件监听器、线程等。
-
代码组织和可读性:内部类可以将相关的类和接口组织在一起,提高代码的可读性和可维护性。
-
访问外部类的成员:成员内部类可以直接访问外部类的成员,包括私有成员,这样可以简化代码并提供更好的代码组织。
需要注意的是,内部类会增加类之间的耦合性,因此在使用内部类时需要谨慎考虑设计和代码结构。同时,内部类的创建和使用语法相对复杂,需要注意语法规则和使用方式。
-
成员内部类:
假设有一个汽车类
(Car),而汽车内部有一个引擎类
(Engine),引擎与汽车之间有密切的关联。在这种情况下,可以将引擎类定义为汽车类的成员内部类。成员内部类可以访问汽车类的私有成员,并且通过外部类的实例来创建和操作引擎对象。 -
静态内部类:
假设有一个图形类
(Shape),而图形类中有一个嵌套的计算工具类
(Calculator),用于计算图形的面积和周长。由于计算工具类不需要访问图形类的实例变量,可以将其定义为静态内部类。静态内部类不依赖于外部类的实例,可以直接访问外部类的静态成员。 -
匿名内部类:
假设有一个按钮类(Button),当按钮被点击时,需要执行某个特定的操作。在这种情况下,可以使用匿名内部类来实现按钮的点击监听器接口。匿名内部类可以快速创建并实现接口,将按钮点击的逻辑直接定义在按钮的点击事件处理中,避免了创建独立的监听器类。 -
方法内部类:
假设有一个订单类(Order),每个订单可以包含多个商品。在订单类的方法中,可能需要定义一个内部类来表示商品对象,并提供一些与订单相关的特定操作。在这种情况下,可以使用方法内部类来定义订单类的特定商品类。方法内部类仅在方法内部可见,可以与订单类的其他成员进行交互。