Java内部类之访问权限和编译效率

在文章【集合框架】之深入分析ArrayList中,发现一个问题如下:

问题1: elementData的注释的意思是,非私有化以简化嵌套类的访问,但嵌套类可以透明地访问外围类的所有成员,如何理解这里的简化?
为什么不声明为private呢?

通过查看反编译查看字节码解决了问题:
虚拟机不知道类的分组情况,会在类中提供非public方法供其他类访问私有成员,也可用于封闭类。内部类在访问外部类私有变量时,编译器会为外部类添加一个非公有方法,内部类通过持有外部类的引用,调用此方法,访问私有变量。

故声明为非私有,可简化编译器添加非公有方法这个操作,提高效率。

如果安全允许且无封装此对象的必要,使用private会加重编译器的负担。


1.内部类访问外部非private变量

public class Outer {
    public int i = 10;
    public class Inner {
        public int j = i;
    }
    public static void main(String[] args) throws InterruptedException {
        Outer outer = new Outer();
        Inner inner = outer.new Inner();
        inner.j = 1;
    }
}

字节码如下
Java内部类之访问权限和编译效率_第1张图片

逐句翻译:

0:aload_0

将Slot 0的元素加载到操作栈(操作数0隐含在指令中)

1:invokespecial #10

调用父类Object的初始化方法

4:aload_0

将Slot 0的元素加载到操作栈

5:bitpush  10

将常量10加载到操作栈

7:putfeild  #12

访问实例字段i

10return

方法正常退出

main函数

0new #1

创建类Outer实例

3:dup

复制栈顶元素

4:invokespecial #23

调用Outer的初始化方法

7:astore_1

将栈顶元素存到局部变量表Slot 1

8new #24

创建类Inner实例

11:dup

复制栈顶元素

12:aload_1

入栈

13:dup

复制栈顶元素

14:invokevirtual   #23

调用对象的实例方法getClass

17pop
18:invokespecial #30

调用Inner的初始化方法

21:astore_2

将栈顶元素存到局部变量表Slot 2

22:aload_2
23:iconst_1
24:putfeild  #33

访问实例字段i

27return

方法退出

2.内部类访问外部private变量

多了一个方法,编译器自动给外部类Outer添加一个方法access$0,访问私有变量i
Java内部类之访问权限和编译效率_第2张图片

There is one more category of compiler-generated members. A private member m of a class C may be used by another class D, if one class encloses the other, or if they are enclosed by a common class. Since the virtual machine does not know about this sort of grouping, the compiler creates a local protocol of access methods in C to allow D to read, write, or call the member m. These methods have names of the form access 0,access 0 , a c c e s s 1, etc. They are never public. Access methods are unique in that they may be added to enclosing classes, not just inner classes.

虚拟机不知道类的分组情况,会在类中提供非public方法供其他类访问私有成员,也可用于封闭类。

看一下Inner的Class文件
Java内部类之访问权限和编译效率_第3张图片

内部类对象会产生名称为this$0的一个字段,该字段保存的是创建这个内部类对象的外部类对象引用,然后调用其access$0方法,为其私有变量i赋值

你可能感兴趣的:(Java)