深入解析内部类(上)
内部类简介
在Java中,如果一个类定义在另一个类或方法内部,则称其为内部类。内部类可以分为成员内部类、局部内部类、匿名内部类和静态内部类。
成员内部类的定义方式
class X {
class Y {}
}
成员内部类的特点
- 成员内部类能够访问外部类的所有成员,包括私有成员。
- 当内部类与外部类拥有相同名称的成员变量或方法时,内部类会隐藏外部类的同名成员,默认情况下直接访问的是内部类的成员。
- 要访问外部类的同名成员,需使用
外部类.this.成员的方式。
接下来通过示例演示上述特点。
示例:定义成员内部类
public class Container {
private float data;
public float getData() {
return data;
}
public void setData(float data) {
this.data = data;
}
public void displayData() {
System.out.println("float data = " + data);
}
class Nested {
private float data = 4.44f;
public float getData() {
return data;
}
public void setData(float data) {
this.data = data;
}
public void showData() {
System.out.println("float data = " + data);
System.out.println("获取Container类的数据=" + Container.this.data);
System.out.println("下面是Container类的displayData()方法");
Container.this.displayData();
}
}
}
测试代码:
public class Demo {
public static void main(String[] args) {
// 错误示范:不能直接创建Nested类实例
// Nested nested = new Nested(); // 编译错误
// 正确做法是先创建Container类实例
Container container = new Container();
// 设置Container类的data值为20
container.setData(20);
// 创建内部类实例
Container.Nested n = container.new Nested();
// 调用内部类方法
n.showData();
}
}
运行结果:
float data = 4.44
Container类的数据=20.0
下面是Container类的displayData()方法
float data = 20.0
根据输出结果与代码对照分析:
- 第一行显示了内部类的
data值。 - 第二行展示了如何通过
Container.this.data访问外部类的data值。 - 第三行演示了如何调用外部类的方法。
匿名内部类
匿名内部类没有名字,在栈中也没有引用存储,因此只能被使用一次。
定义匿名内部类的格式
// 定义匿名内部类
new 父类构造器(参数列表){}
// 对于接口
new 接口名(){}
示例:匿名内部类的应用
首先定义一个接口:
public interface Job {
void performTask();
}
然后在测试类中使用匿名内部类实现该接口:
public class Demo {
public static void main(String[] args) {
executeJob(new Job(){
public void performTask(){
System.out.println("执行任务...");
}
});
}
public static void executeJob(Job j){
j.performTask();
}
}
这相当于创建了一个实现了Job接口的匿名类,并立即创建其实例作为参数传递给executeJob方法。
注意事项
- 匿名内部类默认创建子类或实现类。
- 可以重写父类的部分方法,但必须实现接口的所有方法。
- 不能定义构造函数。
- 不允许存在静态修饰的成员。
- 只能访问final类型的局部变量,实际上所有局部变量在匿名内部类的作用域内都被视为final。