- java类内部的的访问修饰符是为了控制类内成员的可见度,被private修饰的类成员只能在本类体内被访问到,在其他地方无法直接访问,只能通过调用公开的方法接口来调用,这是java封装的基本概念。
- java内部类却在挑战这个概念,请看代码:
/**
* 四种内部类的私有属性,有三种可以被外部类直接访问到
*/
public class Available{
public static void main(String[] args){
Outer outer = new Outer();
outer.local();
}//end main
}//end calss
class Outer{
static class Inner01{//1.静态内部类
private int a = 1;
}
class Inner02{//2.成员内部类
private int b = 2;
}
//局部方法
public void local(){
class Inner03{//3.局部内部类
private int c = 3;
}
Dog dog = new Dog(){//4.匿名内部类
private int d= 4;
};
Inner01 inner01 = new Inner01();
System.out.println(inner01.a);//1.直接访问了静态内部类私有属性
Inner02 inner02 = new Inner02();
System.out.println(inner02.b);//2.直接访问成员内部类私有属性
Inner03 inner03 = new Inner03();
System.out.println(inner03.c);//3.在局部,直接访问局部内部类私有属性
//System.out.println(dog.d);//4.匿名内部类无法访问到私有属性
/*
原因非常简单,因为你匿名内部类其实是一个很正常的类,是一种类组合进入外部类,
只是这种组合只用一次,没必要起名字,因此与正常语法无异,
当然无法在类体外部访问到私有属性
*/
}
}//end Outer
class Dog{}
输出结果:
1
2
3
- 可以看到,静态内部类、成员内部类、局部内部类都可以在内部类体外,直接访问到其私有属性,难道是java语法被挑战了吗?
- 非也非也,我们把这个
Outer.class
通过javap
反编译一下,看看有什么结果:
- 注意标注的地方:
invokestatic
用以调用类方法(Invoke a class (static) method ),我们并没有定义这三个方法呀,它们从哪里来的呢? - 原来,jvm 帮你在内部类中为 private 属性生成了一个 static 的 acess$000 的方法,外部类之所以可以调用内部类的 private,其实是因为隐式的调用了 access$000 方法。这也就是红圈中access$000 | access$100 | access$200的由来了,刚好对应三种可以访问到私有属性的内部类。
- 至于底层到底是如何实现的,有待进一步学习…