在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类。
在 Java 中,内部类分为成员内部类和匿名内部类。
我们先来看一下成员内部类:
1、类中套类,外面的叫外部类,里面的叫内部类
2、内部类通常只服务于外部类,对外不具备可见性
3、内部类对象通常是在外部类中创建
4、内部类可直接访问外部类成员,包括私有的。因为内部类中有个隐式的引用指向创建它的外部类对象。
具体代码如下:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 Mother mother = new Mother(); 4 mother.show(); 5 } 6 } 7 8 class Mother { // 外部类 9 private int age = 10; 10 11 void show() { 12 Son son = new Son(); // 可在外部类中创建 13 son.test(); 14 } 15 16 class Son { // 内部类 17 void test() { 18 System.out.println(age); // 10 19 System.out.println(Mother.this.age); // 10 隐式的引用指向创建它的外部类对象 20 System.out.println(this.age); // 编译错误 21 } 22 } 23 } 24 25 class Test { 26 void show() { 27 Mother mother = new Mother(); 28 Son son = new Son(); // 编译错误,内部类不具备可见性 29 } 30 }
在实际开发中,我们很少会用到成员内部类的写法,通常情况下会用到匿名内部类,如下代码:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 4 // Mother mother = new Mother(); // 编译错误,接口不能实例化 5 6 /** 7 * 1、系统创建了 Mother 的一个子类,没有名字 8 * 2、为该子类创建了一个对象,叫 mother 9 * 3、大括号中的为子类的类体 10 * */ 11 Mother mother = new Mother() { 12 }; 13 } 14 } 15 16 interface Mother { 17 18 }
在之前我们说过接口能不能被实例化,否则会出现编译错误,但如果我们在实例化的接口后面添加一对大括号,系统则会隐式地为我们创建一个子类,这样就不会出现编译错误了,我们可以再形象地来看一下上面的解释,如下代码:
1 public class HelloWorld { 2 public static void main(String[] args) { 3 4 // 向上造型 5 Mother mother1 = new Son(); 6 mother1.show(); // son 7 8 final int num = 10; 9 // 匿名内部类 10 Mother mother2 = new Mother() { 11 public void show() { 12 System.out.println("mother"); // mother 13 System.out.println(num); // num 14 } 15 }; 16 mother2.show(); // mother 17 } 18 } 19 20 interface Mother { 21 void show(); 22 } 23 24 class Son implements Mother { 25 public void show() { 26 System.out.println("son"); 27 } 28 }
在上面的代码中,我们可以通过之前讲过的向上造型的方法,重写 Mother 中的 show() 方法来实现程序的正常运行,同时我们也可以通过上面说的匿名内部类的方法来实现,即在实例后面添加一对大括号,并将 Mother 内的 show() 方法重写,这样所运行的结果和向上造型的实现结果是一样的。
匿名内部类:
1、如果想创建一个类的对象,并且对象只被创建一次,此时该类不必命名,称为匿名内部类。
2、匿名内部类中访问外部的数据,该数据必须是 final 类型。