我们一般使用的java内部类有4种形式:一般内部类、局部内部类、匿名内部类、静态内部类。以下是我作的一个测试,以说明各种内部类的特性。
有关内部类的特性,代码中有详细说明,如下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
/* * java内部类测试 * * InterObj反射结果: * * private int i * private InterObj$InterA ia * public InterObj() * public static void main(java.lang.String[]) * private int getI() * public void p() * public void pi() * public void pp() * public static void ppp() * public void pppp() * 下面是编译器自动生成用于访问私有属性或方法package级别的static方法 * static int access$0(InterObj) */ public class InterObj { private int i=8; private InterA ia=null; public InterObj(){ ia=new InterA(); } private int getI(){ return i; } public void p(){ pi(); pp(); ppp(); pppp(); } /* * 在一般内部类中可以访问“外套类”中的任何级别的方法和属性。而外套类也同样可以 * 访问“内部类”中的任何级别的方法和属性。因为内部类可以持有对外套类对象的引用。 * 而“外套类”对于自己的需要被内部类访问的私有方法和属性,编译器都会自动生成与 * 私有方法和属性相对应的“package”级别的static方法,这些方法需要用外部类对象作 * 为参数,这样就可以在“package”级别的static方法中通过访问外套类中的私有方法和 * 属性了。 * 而对于外套类要访问内部类中的私有方法和属性,也是同样的原理,内部类在编译时, * 会生成与需要被外套类访问的私有方法、属性相对应的“package”级别的static方法。 * * InterA反射结果: * private int ia * 下面是内部类持有的外套类对象引用 * final InterObj this$0 * 构造函数中用外套类对象作为参数 * InterObj$InterA(InterObj) * private void pA() * 下面是编译器自动生成用于访问私有属性或方法package级别的static方法 * static void access$0(InterObj$InterA) * public void pA1() * */ class InterA{ private int ia=9; private void pA(){ System.out.println("this is InterA.pA: ia="+ia+",InterObj.i="+getI()); } public void pA1(){ System.out.println("this is InterA.pA1: ia="+ia+",InterObj.i="+getI()); } } /* * 局部内部类,只在方法内部可见,其它特性与一般内部类相同。 * 对需要访问的局部变量,必需设置成final,因为局部内部类虽然可以持有对外套类对象的 * 引用来访问外部类的属性和方法,但是却不能访问外部类方法中局部变量,所有编译器就 * 在局部内部类中“拷贝”了一份需要访问的局部变量(但是对于基本类型int,float和String * 等值不发生改变的类型没有拷贝)为了保证拷贝的变量值和外部方法中的变量的值所指向的 * 对象是同一 个对象,所以要求那些被局部类使用的局部变量应该设置成final,而不能被修 * 改,这样来保证局部内中拷贝的变量和外部方法中的变量所指向的是同一个对象。变量设 * 置成final只是控制变量指向的对象地址不变,而不是它指向的对象的内部属性不能改变。 * * InterB的反射结果: * * private int ib * 下面是内部类持有的外套类对象引用 * final InterObj this$0 * 下面是内部类持有的外部方法中的局部变量Test对象的引用拷贝 * private final Test val$test * 构造函数中用外套类对象和局部变量Test作为参数 * InterObj$1$InterB(InterObj,Test) * private void pB() * 下面是编译器自动生成用于访问私有属性或方法package级别的static方法 * static void access$0(InterObj$1$InterB) */ public void pi(){ final int s=5; final Test test=new Test(); class InterB{ private int ib=7; private void pB(){ System.out.println("this is InterB.pB: ib="+ib+ ",(Method)pi.s="+s+",Test.t="+test.getT()); } } InterB ib=new InterB(); //此处改变了被局部内部类引用了的Test test的内部状态。 //结果调用ib.pB()时,输出的就是改变后的值100 test.setT(100); ib.pB(); } /* * 静态内部类,在不需要持有对“外套类对象”的引用时使用。 * * InterC反射结果:(静态内部类没有对外套类对象的引用) * private int ic * InterC() * private void pC() */ static class InterC{ private int ic=6; private void pC(){ System.out.println("this is InterC.pC: ic="+ic); } } /* * 非静态方法,可以构造静态和非静态的内部类。 * 可以访问内部类中任何权限的属性和方法 */ public void pp(){ InterA ia=new InterA(); ia.pA(); ia.pA1(); InterC ic=new InterC(); ic.pC(); //局部内部类,只在方法内部可见 //InterB ib=new InterB(); } /* * 静态方法,只能构造静态的内部类。 * 不能构造非静态的内部类,因为静态方法中没有this来引用“外套类”的对象,来构造 * 需要引用外套类对象引用的内部类对象。 */ public static void ppp(){ //InterA ia=new InterA(); //但是可以如下构造: InterObj iobj=new InterObj(); InterA ia=iobj.new InterA(); ia.pA(); ia.pA1(); InterC ic=new InterC(); ic.pC(); //局部内部类,只在方法内部可见 //InterB ib=new InterB(); } /* * 匿名内部类测试 */ public void pppp(){ TestInterface tif=new TestInterface(){ public void pppp() { System.out.println("TestInterface.noName"); } } ; tif.pppp(); } /* * 运行结果: * this is InterB.pB: ib=7,(Method)pi.s=5,Test.t=100 * this is InterA.pA: ia=9,InterObj.i=8 * this is InterA.pA1: ia=9,InterObj.i=8 * this is InterC.pC: ic=6 * this is InterA.pA: ia=9,InterObj.i=8 * this is InterA.pA1: ia=9,InterObj.i=8 * this is InterC.pC: ic=6 * TestInterface.noName */ public static void main(String[] args) { InterObj io=new InterObj(); io.p(); } } /* * 用于创建内部类的接口 */ interface TestInterface{ public void pppp(); } /* * 用于测试局部内部类的局部变量类 */ class Test{ private int t= 9 ; public int getT(){ return t; } public void setT( int t1){ t=t1; } } |
再分享一则实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
public class InnerClass { static Toy toy = new Toy(){ String name = "老吴" ; @Override public void jump() { System.out.println(name+ "跳出地球" ); go(); } public void go(){ System.out.println( "奔跑" ); } } ; /*内部类:定义在类的内部的类 *1.成员内部类: *1.1成员内部类可以直接访问外部类的属性 *1.2通过 外部类名.this 这种方式访问外部类的当前对象 *成员内部类实例化对象: 外部类名.内部类名 引用名 = 外部类对象.new 内部类名(); *2.静态内部类 *2.1静态内部类内部不能访问外部类的成员资源,只能通过类名访问外部类的静态资源 *静态内部类实例化对象: 外部类名.内部类名 引用名 = new 外部类名.内部类名(); *3.局部内部类: *3.1也可以直接访问外部类的属性 *3.2也可以通过 外部类名.this 访问外部类当前对象 *3.3局部内部类只能在方法内部被访问,修饰符只能是默认的 *4.匿名内部类:在需要一个类的具体子类实例的时候,临时的生成一个类使用 *new 类名(){ * 重写方法; *}; *4.1匿名内部类访问外部方法的属性,该属性会被转换为常量 *4.2匿名内部类中新增的属性和方法,只能在匿名内部类内部使用 * */ public static void main(String[] args) { Person per = new Person("老陈",18); Person.Computer pc = per.new Computer("外星人"); Person.Computer pc1 = new Person("简自豪",18).new Computer("外星人"); pc.runGame(); pc1.runGame(); Person.Computer1 pc11 = new Person.Computer1("网吧的电脑"); pc11.runGame(); per.useComputer(); String str = "啦啦啦"; //str = "罗库偶偶"; Computer com = new Computer(){ @Override public void runGame() { // TODO Auto-generated method stub System.out.println(per.age+"岁的"+per.name+"在玩啦啦啦啦啦德玛西塔"); System.out.println(str); } } ; com.runGame(); //具体类的匿名内部类独享 /*Toy toy = new Toy(){ @Override public void jump() { System.out.println("跳出地球"); } };*/ toy.jump(); toy.jump(); //toy.go(); //System.out.println(toy.); } } class Person { String name; int age; static int age1 = 18 ; static String name1 = "全职高手" ; public Person(String name, int age) { super (); this .name = name; this .age = age; } public void playGame(){ System.out.println(name+ "玩游戏" ); } public class Computer{ String name; public Computer(String name) { super (); this .name = name; } public void runGame(){ System.out.println(name+ "运行游戏" ); System.out.println(age+ "岁的" +Person. this .name+ "玩游戏" ); } } public static class Computer1{ String name; public Computer1(String name) { super (); this .name = name; } public void runGame(){ System.out.println(name+ "运行游戏" ); System.out.println(Person.age1+ "的" +Person.name1+ "在玩游戏" ); } } public void useComputer(){ class Computer{ String name; public Computer(String name) { super (); this .name = name; } public void runGame(){ System.out.println(name+ "运行游戏" ); System.out.println(Person. this .age+ "的" +Person. this .name+ "正在玩游戏" ); } } Computer com = new Computer( "笔记本" ); com.runGame(); } } public interface Computer { void runGame(); } public class Toy { public void jump(){ System.out.println( "玩具跳一下" ); } } |
总结
以上就是本文关于java内部测试类代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
原文链接:http://blog.csdn.net/wanghuiwei888/article/details/78797620