从字节码的角度看Java内部类与外部类的互相访问(二)

2014-11-24 00:38:42 · 作者: · 浏览: 4
#6;// "":()V
20 const #10 = Asciz LineNumberTable;
21 const #11 = Asciz LocalVariableTable;
22 const #12 = Asciz this;
23 const #13 = Asciz LTest;;
24 const #14 = Asciz main;
25 const #15 = Asciz ([Ljava/lang/String;)V;
26 const #16 = Method #1.#9; // Test."":()V
27 const #17 = Method #1.#18; // Test.initData:()V
28 const #18 = NameAndType #19:#6;// initData:()V
29 const #19 = Asciz initData;
30 const #20 = Asciz args;
31 const #21 = Asciz [Ljava/lang/String;;
32 const #22 = class #23; // Test$A
33 const #23 = Asciz Test$A;
34 const #24 = Method #22.#25; // Test$A."":(LTest;LTest$A;)V
35 const #25 = NameAndType #5:#26;// "":(LTest;LTest$A;)V
36 const #26 = Asciz (LTest;LTest$A;)V;
37 const #27 = Method #22.#28; // Test$A.access$1:(LTest$A;I)V
38 const #28 = NameAndType #29:#30;// access$1:(LTest$A;I)V
39 const #29 = Asciz access$1;
40 const #30 = Asciz (LTest$A;I)V;
41 const #31 = class #32; // Test$B
42 const #32 = Asciz Test$B;
43 const #33 = Method #31.#34; // Test$B."":(LTest$B;)V
44 const #34 = NameAndType #5:#35;// "":(LTest$B;)V
45 const #35 = Asciz (LTest$B;)V;
46 const #36 = Method #31.#37; // Test$B.access$1:(LTest$B;I)V
47 const #37 = NameAndType #29:#38;// access$1:(LTest$B;I)V
48 const #38 = Asciz (LTest$B;I)V;
49 const #39 = Asciz SourceFile;
50 const #40 = Asciz Test.java;
51 const #41 = Asciz InnerClasses;
52 const #42 = Asciz A;
53 const #43 = Asciz B;
54
55 {
56 public Test();
57 Code:
58 Stack=1, Locals=1, Args_size=1
59 0: aload_0
60 1: invokespecial #8; //Method java/lang/Object."":()V
61 4: return
62 LineNumberTable:
63 line 1: 0
64
65 LocalVariableTable:
66 Start Length Slot Name Signature
67 0 5 0 this LTest;
68
69
70 public static void main(java.lang.String[]);
71 Code:
72 Stack=2, Locals=1, Args_size=1
73 0: new #1; //class Test
74 3: dup
75 4: invokespecial #16; //Method "":()V
76 7: invokespecial #17; //Method initData:()V
77 10: return
78 LineNumberTable:
79 line 5: 0
80 line 6: 10
81
82 LocalVariableTable:
83 Start Length Slot Name Signature
84 0 11 0 args [Ljava/lang/String;
85
86
87 }
复制代码
  从进入initData方法栈后的代码分析,首先是调用了A的方法,这个方法是自动生成的两个方法之一,用于调用A的构造函数(另外一个是,用于在 虚拟机第一次加载.class时初始化静态变量等),随后访问了A中的private变量,通过.操作符的访问已经被更替为const #27 = Method #22.#28; // Test$A.access$1:(LTest$A;I)V,虽然没法知道#22.#28代表的含义,不过javap已经很人性化地给我们加上了注释,标明这一段就是在调用A中的access方法,而后面$1的含义表示这是A中第一个private变量;对B中private变量的访问大体相同,不再多说。至此,我们已经可以回答第二个问题,外部类是通过内部类隐含的access静态方法来访问其中的private变量的,并没有破坏private修饰符的作用原则。