@@ -379,6 +379,84 @@ public class OutterClass
379
379
}
380
380
```
381
381
382
+ ** 为什么内部类可以使用外部类的private属性** :
383
+
384
+ 我们在InnerClass中增加一个方法,打印外部类的userName属性
385
+
386
+ ``` java
387
+ // 省略其他属性
388
+ public class OutterClass {
389
+ private String userName;
390
+ ......
391
+ class InnerClass {
392
+ ......
393
+ public void printOut (){
394
+ System . out. println(" Username from OutterClass:" + userName);
395
+ }
396
+ }
397
+ }
398
+
399
+ // 此时,使用javap -p命令对OutterClass反编译结果:
400
+ public classOutterClass {
401
+ private String userName;
402
+ ......
403
+ static String access$000(OutterClass );
404
+ }
405
+ // 此时,InnerClass的反编译结果:
406
+ class OutterClass $InnerClass {
407
+ final OutterClass this $0 ;
408
+ ......
409
+ public void printOut ();
410
+ }
411
+
412
+ ```
413
+
414
+ 实际上,在编译完成之后,inner实例内部会有指向outer实例的引用` this$0 ` ,但是简单的` outer.name ` 是无法访问private属性的。从反编译的结果可以看到,outer中会有一个桥方法` static String access$000(OutterClass) ` ,恰好返回String类型,即userName属性。正是通过这个方法实现内部类访问外部类私有属性。所以反编译后的` printOut() ` 方法大致如下:
415
+
416
+ ``` java
417
+ public void printOut() {
418
+ System . out. println(" Username from OutterClass:" + OutterClass . access$000(this . this $0 ));
419
+ }
420
+ ```
421
+
422
+ 补充:
423
+
424
+ 1 . 匿名内部类、局部内部类、静态内部类也是通过桥方法来获取private属性。
425
+ 2 . 静态内部类没有` this$0 ` 的引用
426
+ 3 . 匿名内部类、局部内部类通过复制使用局部变量,该变量初始化之后就不能被修改。以下是一个案例:
427
+
428
+ ``` java
429
+ public class OutterClass {
430
+ private String userName;
431
+
432
+ public void test (){
433
+ // 这里i初始化为1后就不能再被修改
434
+ int i= 1 ;
435
+ class Inner {
436
+ public void printName (){
437
+ System . out. println(userName);
438
+ System . out. println(i);
439
+ }
440
+ }
441
+ }
442
+ }
443
+ ```
444
+
445
+ 反编译后:
446
+
447
+ ``` java
448
+ // javap命令反编译Inner的结果
449
+ // i被复制进内部类,且为final
450
+ class OutterClass $1Inner {
451
+ final int val$i;
452
+ final OutterClass this $0 ;
453
+ OutterClass$1Inner ();
454
+ public void printName ();
455
+ }
456
+
457
+ ```
458
+
459
+
382
460
### 条件编译
383
461
384
462
—般情况下,程序中的每一行代码都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。
0 commit comments