在 Java 中,内部类是指定义在另一个类内部的类。根据定义的位置和方式不同,内部类可以分为:成员内部类 、静态内部类 、局部内部类 和 匿名内部类。本文将对这四种内部类进行详细讲解,并给出代码示例和使用场景。
一、什么是内部类?
内部类 就是写在一个类里面的类。
它的主要作用是增强封装性,让某个类仅在外部类的范围内使用,或者表示一种"所属关系"。
二、什么时候使用内部类?
当一个类所表示的事物是另一个类的一部分,且单独存在没有意义时,适合使用内部类。
例如:
-
汽车的发动机
-
人的心脏
三、成员内部类(了解)
定义位置:成员位置(与属性、方法同级),属于外部类的成员。
特点:
-
可以被
private、default、protected、public、static等修饰符修饰。 -
在 JDK 16 之前,成员内部类中不能定义静态变量;JDK 16 开始可以定义静态变量。
示例代码:
java
public class Car {
String carName;
int carAge;
int carColor;
class Engine { // 成员内部类
String engineName;
int engineAge;
}
}
获取成员内部类对象的方式:
方式一:外部类提供方法返回内部类对象。
java
public class Car {
String carName;
int carAge;
int carColor;
// 成员内部类
class Engine {
String engineName;
int engineAge;
public void show() {
System.out.println("发动机名称:" + engineName);
System.out.println("发动机年龄:" + engineAge);
}
}
// 方式一:外部类提供方法返回内部类对象
public Engine getEngine() {
return new Engine();
}
}
// 使用示例
public class Test {
public static void main(String[] args) {
// 方式一:通过外部类的方法获取内部类对象
Car car = new Car();
// 直接获取
Car.Engine engine1 = car.getEngine();
}
}
方式二:直接创建。
java
Outer.Inner oi = new Outer().new Inner();
变量访问规则:
当内部类与外部类存在同名变量时,可以通过 this 和 外部类名.this 区分:
java
public class Outer {
private int a = 10;
class Inner {
private int a = 20;
public void show() {
int a = 30;
System.out.println(a); // 30
System.out.println(this.a); // 20
System.out.println(Outer.this.a); // 10
}
}
}
四、静态内部类
定义位置 :成员位置,使用 static 修饰。
特点:
-
只能直接访问外部类中的静态变量和静态方法
-
若想访问外部类的非静态成员,必须创建外部类的对象
-
静态内部类本身可以包含静态成员和非静态成员
-
不需要外部类对象就可以创建静态内部类的对象
示例代码:
java
public class Car {
// 外部类的成员变量
String carName = "宝马"; // 非静态变量
static String brand = "BMW"; // 静态变量
int carAge = 2; // 非静态变量
// 外部类的成员方法
public void start() {
System.out.println("汽车启动");
}
public static void staticMethod() {
System.out.println("外部类的静态方法");
}
// 静态内部类
static class Engine {
String engineName = "V8发动机"; // 非静态变量
static int engineCount = 4; // 静态变量
public void show() {
// 1. 可以直接访问外部类的静态成员
System.out.println("外部类的静态变量: " + brand);
staticMethod(); // 可以直接调用外部类的静态方法
// 2. 不能直接访问外部类的非静态成员
// System.out.println(carName); // 编译错误!
// start(); // 编译错误!
// 3. 访问外部类非静态成员需要创建外部类对象
Car car = new Car();
System.out.println("外部类的非静态变量: " + car.carName);
car.start();
// 4. 访问自己的成员
System.out.println("发动机名称: " + engineName);
System.out.println("发动机数量: " + engineCount);
}
public static void staticShow() {
// 静态方法中只能直接访问外部类的静态成员
System.out.println("外部类的静态变量: " + brand);
// 不能直接访问自己的非静态成员
// System.out.println(engineName); // 编译错误!
// 需要创建对象才能访问非静态成员
Engine engine = new Engine();
System.out.println("发动机名称: " + engine.engineName);
}
}
}
五、局部内部类
定义位置:方法内部。
特点:
-
类似于局部变量,外界无法直接使用。
-
必须在方法内部创建对象并使用。
-
可以直接访问外部类的成员,也可以访问方法内的局部变量。
示例代码:
java
public class Outer {
public void method() {
class LocalInner {
public void show() {
System.out.println("局部内部类");
}
}
LocalInner li = new LocalInner();
li.show();
}
}
六、匿名内部类
定义位置:成员位置或局部位置。
特点:
-
没有名字的内部类。
-
本质是:一个没有名字的 Java 类 + 实现接口/继承类 + 重写方法 + 创建对象。
-
常用于只需要使用一次的类实现,简化代码。
格式:
java
new 类名或接口名() {
重写方法;
};
示例代码:
java
Inter inter = new Inter() {
public void show() {
System.out.println("匿名内部类实现");
}
};
使用场景:
-
实现接口或继承类,且该类只使用一次。
-
是 Lambda 表达式的前置知识点。