这个系列是帮助复习 Java 的基础知识的,但是并不会按照一个特定的顺序。现在开始复习下内部类的相关知识。
0. 简介
内部类的定义很简单,它其实就是在一个类里面定义了另一个类,但是这个定义还是有很多细节需要掌握的。
1. 非静态内部类
1.1 定义
非静态内部类就是在一个类的内部里面定义了一个没有用 static 修饰的类。
1.2 访问控制符
内部类的访问控制符 | 访问范围 |
---|---|
private | 同一个类 |
default | 同一个类,同一包中 |
protected | 同一个类,子类,同一包中 |
public | 任何位置 |
1.3 非静态内部类访问外部类元素
非静态内部类是可以访问外部类的任何实例变量和方法,包括 private 修饰的成员变量。现在用一个例子来说明一下,代码如下:
public class Outer {
private int a = 10;
private void innerCall() {
System.out.println("Inner Call");
}
private class Inner {
public void printInfo() {
System.out.println("a = " + a);
innerCall();
}
}
public void test() {
Inner inner = new Inner();
inner.printInfo();
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.test();
}
}
输出结果:
a = 10
Inner Call
从输出的结果就可以看到,非静态内部类是可以访问到外部类的任何实例变量和方法的。
那为什么内部类可以直接访问外部类的实例变量和方法呢?因为内部类里面是持有外部类的实例引用,一个非静态内部类创建时必然会有其外部类实例的引用。也就是说上面的 printInfo() 方法也可以写成如下:
public void printInfo() {
System.out.println("a = " + Outer.this.a);
Outer.this.innerCall();
}
上述代码中的 Outer.this 就是非静态内部类持有外部类的实例引用。
1.3.1 非静态内部类方法访问某个变量的检查顺序
当非静态内部类的方法访问某个变量是按一定顺序来查找的,顺序如下
- 在该方法的局部变量找
- 方法所在的内部类找
- 内部类所在的外部类找
- 如果都没有则编译报错
举个例子,代码如下:
public class Outer {
private int a = 10;
private class Inner {
private int a = 9;
public void printInfo(int a) {
System.out.println("a = " + a);
}
}
public void test() {
Inner inner = new Inner();
inner.printInfo(8);
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.test();
}
}
以上代码的输出结果就是 a = 8。
如果把 printInfo(int a) 的形参 a 去掉,则输出的结果为 a = 9。
再把 Inner 类中的成员变量 a 去掉,则输出的结果为 a = 10。
各位可以自己尝试一下,这里就不再讲解。
## 1.4 外部类访问非静态内部类的元素
外部类不能直接访问非静态内部类的实例变量和方法,如果想要访问的话,必须要创建非静态内部类的实例进而调用该实例的成员。如下代码所示:
public class Outer {
private int a = 10;
private class Inner {
public void printInfo() {
System.out.println("a = " + a);
}
}
public void test() {
//这句会编译错误
printInfo();
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.test();
}
}
以上代码会编译错误,如果想要访问的话只能创建 Inner 的实例访问该方法,这里有两种方式,一种就是在 test() 方法里面创建 Inner 对象,另一种就是在 main 方法创建,以下两种方法都用代码试一下:
public class Outer {
private int a = 10;
private class Inner {
public void printInfo() {
System.out.println("a = " + a);
}
}
public void test() {
new Inner().printInfo();
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().printInfo();
outer.test();
}
}
从以上代码可以看到,test() 方法里面直接 new Inner() 即可调用 Inner 方法。不过在 main 方法里要先创建 Outer 对象才可以再调用 new Inner()。
1.4.1 外部类的静态方法不可以创建非静态内部类
根据 Java 的规则,静态成员是不可以访问非静态成员的。非静态内部类其实就是类实例中的一个成员,所以在外部类的静态方法不可以创建非静态内部类,现用代码举例:
public class Outer {
private int a = 10;
private class Inner {
public void printInfo() {
System.out.println("a = " + a);
}
}
public static void main(String[] args) {
//这句代码会编译报错
Inner inner = new Inner();
}
}