成员内部类
除了成员变量、成员方法和构造可作为类的成员外,成员内部类也可以作为类的成员,成员内部类的语法如下:
public class Demo{ //外部类
class Demos{ //内部类
}
}
如果外部类的成员方法和成员变量都被private修饰,但仍可以在内部类中使用。如下图:
创建内部类对象与创建普通类对象的方式相同,都用到了关键字new,如果在外部类中初始化一个内部类对象,那么内部类对想就会绑定在外部类对象上,下面来看一个例子模拟发动机点火。
创建Car类,Car类中有自由属性brand()和start()方法,然后在Car类的内部创建Engine类,Engine类中有私有属性mode()方法和ignite()方法,代码如下:
public class Car { // 创建汽车类
private String brand; // 汽车品牌
public Car(String brand) { // 汽车类的构造方法,参数为汽车品牌
this.brand = brand; // 给汽车品牌赋值
}
class Engine { // 发动机类(内部类)
String model; // 发动机型号
public Engine(String model) { // 发动机类的构造方法,参数为发动机型号
this.model = model; // 给发动机型号赋值
}
public void ignite() { // (发动机)点火方法
System.out.println("发动机" + this.model + "点火");
}
}
public void start() { // 启动(汽车)方法
System.out.println("启动" + this.brand);
}
public static void main(String[] args) {
Car car = new Car("大众朗行"); // 创建汽车类对象,并为汽车品牌赋值
car.start(); // 汽车类对象调用启动(汽车)方法
// 创建发动机类(内部类)对象,并为发动机型号赋值
Car.Engine engine = car.new Engine("EA211");
engine.ignite(); // 发动机类对象调用(发动机)点火方法
}
}
返回结果:
启动大众朗行
发动机EA211点火
匿名内部类
匿名内部类的特点是只需要使用一次,也就是说,匿名内部类不能被重复使用,即创建匿名内部类的实例后,这个匿名内部列立即消失,匿名类的所有实现代码都需要在大括号之间进行编写,最常用的创建匿名内部类的方式是创建某个接口类型或抽象类的对象,语法如下:
new A() {
//匿名内部类的类体
};
其中A指代的是接口名或抽象类的类名。
下面举个例子,代码如下:
abstract class FreshKeepingFilm { // 创建“保鲜膜”抽象类
abstract void pack(); // 定义抽象的包装方法
}
public class Sausage { // 创建香肠类
public static void main(String[] args) {
new FreshKeepingFilm() { // 创建匿名内部类FreshKeepingFilm的对象
@Override
void pack() { // 重写抽象的包装方法
System.out.println("缠上保鲜膜为香肠保鲜");
}
}.pack(); // 匿名内部类FreshKeepingFilm的对象调用重写抽象的包装方法
}
}
使用匿名内部类时应该遵守以下原则:
- 匿名类没有构造方法;
- 匿名类不能定义静态的成员;
- 匿名类不能用private、public、protected、static、final、abstract等修饰符;
- 只可以创建一个匿名类实例;
什么情况下会使用匿名内部类?
匿名内部类和其他类有着相同的内存结构,只不过匿名内部类创建出的对象没有被具体的变量所引用,所以匿名内部类是一次性的,如果创建出的类对象有且仅使用一次,在这种场景中就可以考虑使用匿名内部类。