1、内部类访问特点:
- 内部类可以直接访问外部类的成员,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
- 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //外部类名.内部类名 = 外部类对象.内部类对象 4 Outer.Inner oi = new Outer().new Inner(); //创建内部类对象 5 oi.method(); 6 7 } 8 } 9 10 class Outer { 11 private int num = 10; 12 class Inner { 13 public void method() { 14 System.out.println(num); 15 } 16 } 17 }
2、私有成员内部类
- 通过本类中提供一个公共的方法来访问私有成员内部类。
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //Outer.Inner oi = new Outer().new Inner(); 4 //oi.method(); //这种方法不可以访问,因为成员内部类已经私有了 5 6 Outer o = new Outer(); 7 o.print(); 8 } 9 } 10 11 class Outer { 12 private int num = 10; 13 private class Inner { 14 public void method() { 15 System.out.println(num); 16 } 17 } 18 19 //本类中提供一个公共的访问方式,通过本类中的方法访问私有成员内部类 20 public void print() { 21 Inner i = new Inner(); 22 i.method(); 23 } 24 }
3、静态成员内部类
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 //外部类名.内部类名 对象名 = 外部类名.内部类对象; 4 //其实这句话中new的位置是在Inner()前,new是修饰Inner()的:Outer.new Inner(); 5 //但是一般将new提到最前面,否则编译会报错,所以就写成下面这样了 6 Outer.Inner oi = new Outer.Inner(); 7 oi.method(); 8 //内部类里面静态方法的访问特点:外部类.内部类.静态方法名(); 9 Outer.Inner2.print(); 10 } 11 } 12 13 class Outer { 14 static class Inner { 15 public void method() { 16 System.out.println("method"); 17 } 18 } 19 20 static class Inner2 { 21 public static void print() { 22 System.out.println("print"); 23 } 24 } 25 }
4、局部内部类访问局部变量
- 局部内部类访问局部变量,该局部变量必须用final修饰
- 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
* 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了。如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。
* 但是jdk 1.8取消了这个事情,所以我认为这是个bug。
- 例:
1 class Demo { 2 public static void main(String[] args) { 3 Outer o = new Outer(); 4 //o.run(); //错误,因为Inner在method方法中,属于局部成员。方法外无法访问 5 o.method(); 6 } 7 } 8 9 class Outer { 10 public void method() { 11 //int num = 10; //错误: 从内部类中访问本地变量num; 需要被声明为最终类型 12 final int num=10; 13 class Inner { 14 public void print() { 15 System.out.println(num); 16 } 17 } 18 19 Inner i = new Inner(); 20 i.print(); 21 } 22 23 /*public void run() { 24 Inner i = new Inner(); //局部内部类,只能在其所在的方法中访问 25 i.print(); 26 }*/ 27 }
5、面试题
- 例:
1 class Test { 2 public static void main(String[] args) { 3 Outer.Inner oi = new Outer().new Inner(); 4 oi.show(); 5 } 6 } 7 //要求:使用已知的变量,在控制台输出30,20,10。 8 //内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用。外部类名.this 9 class Outer { 10 public int num = 10; 11 class Inner { 12 public int num = 20; 13 public void show() { 14 int num = 30; 15 System.out.println(num); 16 System.out.println(this.num); 17 //System.out.println(new Outer().num); //使用对象来访问成员变量 18 System.out.println(Outer.this.num); 19 } 20 } 21 }
6、个人总结:
- 普通内部类可通过在别的类中直接实例化访问,或者将该内部类的实例化写在该内部类所在的类中的一个方法里,外部通过调用该方法访问内部类。
- 私有成员内部类是将内部类的实例化放在了该内部类所在的类中的一个方法里,该方法提供了一个可供外部公共访问的方式,外部可通过该方法访问私有成员内部类。
- 静态成员内部类与普通内部类相似,可在别的类中直接(实例化)访问或在该内部类所在的类中写一个方法用来(实例化)访问该内部类。只不过静态成员内部类可通过类名调用来访问。
- 局部内部类是将该内部类的实例化直接写在了该内部类所在的方法体中,因为它相当于一个局部变量,在方法体外是访问不到的。