@@ -246,7 +246,7 @@ public static transient void print(String strs[])
246246}
247247```
248248
249- 从反编译后代码可以看出,可变参数在被使用的时候,他首先会创建一个数组,数组的长度就是调用该方法是传递的实参的个数,然后再把参数值全部放到这个数组当中,然后再把这个数组作为参数传递到被调用的方法中。(注:` trasient ` 仅在修饰成员变量时有意义,此处 “修饰方法” 是由于在 javassist 中使用相同数值分别表示 ` trasient ` 以及 ` vararg ` ,见 [ 此处] ( https://github.com/jboss-javassist/javassist/blob/7302b8b0a09f04d344a26ebe57f29f3db43f2a3e/src/main/javassist/bytecode/AccessFlag.java#L32 ) 。)
249+ 从反编译后代码可以看出,可变参数在被使用的时候,他首先会创建一个数组,数组的长度就是调用该方法是传递的实参的个数,然后再把参数值全部放到这个数组当中,然后再把这个数组作为参数传递到被调用的方法中。(注:` transient ` 仅在修饰成员变量时有意义,此处 “修饰方法” 是由于在 javassist 中使用相同数值分别表示 ` transient ` 以及 ` vararg ` ,见 [ 此处] ( https://github.com/jboss-javassist/javassist/blob/7302b8b0a09f04d344a26ebe57f29f3db43f2a3e/src/main/javassist/bytecode/AccessFlag.java#L32 ) 。)
250250
251251### 枚举
252252
@@ -263,7 +263,8 @@ public enum t {
263263然后我们使用反编译,看看这段代码到底是怎么实现的,反编译后代码内容如下:
264264
265265``` java
266- public final class T extends Enum
266+ // Java编译器会自动将枚举名处理为合法类名(首字母大写): t -> T
267+ public final class T extends Enum
267268{
268269 private T (String s , int i )
269270 {
@@ -308,7 +309,7 @@ public final class T extends Enum
308309** 内部类之所以也是语法糖,是因为它仅仅是一个编译时的概念,` outer.java ` 里面定义了一个内部类` inner ` ,一旦编译成功,就会生成两个完全不同的` .class ` 文件了,分别是` outer.class ` 和` outer$inner.class ` 。所以内部类的名字完全可以和它的外部类名字相同。**
309310
310311``` java
311- public class OutterClass {
312+ public class OuterClass {
312313 private String userName;
313314
314315 public String getUserName () {
@@ -337,10 +338,10 @@ public class OutterClass {
337338}
338339```
339340
340- 以上代码编译后会生成两个 class 文件:` OutterClass $InnerClass.class` 、` OutterClass .class` 。当我们尝试对` OutterClass .class` 文件进行反编译的时候,命令行会打印以下内容:` Parsing OutterClass .class...Parsing inner class OutterClass $InnerClass.class... Generating OutterClass .jad ` 。他会把两个文件全部进行反编译,然后一起生成一个` OutterClass .jad` 文件。文件内容如下:
341+ 以上代码编译后会生成两个 class 文件:` OuterClass $InnerClass.class` 、` OuterClass .class` 。当我们尝试对` OuterClass .class` 文件进行反编译的时候,命令行会打印以下内容:` Parsing OuterClass .class...Parsing inner class OuterClass $InnerClass.class... Generating OuterClass .jad ` 。他会把两个文件全部进行反编译,然后一起生成一个` OuterClass .jad` 文件。文件内容如下:
341342
342343``` java
343- public class OutterClass
344+ public class OuterClass
344345{
345346 class InnerClass
346347 {
@@ -353,16 +354,16 @@ public class OutterClass
353354 this . name = name;
354355 }
355356 private String name;
356- final OutterClass this $0 ;
357+ final OuterClass this $0 ;
357358
358359 InnerClass ()
359360 {
360- this . this $0 = OutterClass . this ;
361+ this . this $0 = OuterClass . this ;
361362 super ();
362363 }
363364 }
364365
365- public OutterClass ()
366+ public OuterClass ()
366367 {
367368 }
368369 public String getUserName ()
@@ -385,37 +386,37 @@ public class OutterClass
385386
386387``` java
387388// 省略其他属性
388- public class OutterClass {
389+ public class OuterClass {
389390 private String userName;
390391 ......
391392 class InnerClass {
392393 ......
393394 public void printOut (){
394- System . out. println(" Username from OutterClass :" + userName);
395+ System . out. println(" Username from OuterClass :" + userName);
395396 }
396397 }
397398}
398399
399- // 此时,使用javap -p命令对OutterClass反编译结果 :
400- public classOutterClass {
400+ // 此时,使用javap -p命令对OuterClass反编译结果 :
401+ public classOuterClass {
401402 private String userName;
402403 ......
403- static String access$000(OutterClass );
404+ static String access$000(OuterClass );
404405}
405406// 此时,InnerClass的反编译结果:
406- class OutterClass $InnerClass {
407- final OutterClass this $0 ;
407+ class OuterClass $InnerClass {
408+ final OuterClass this $0 ;
408409 ......
409410 public void printOut ();
410411}
411412
412413```
413414
414- 实际上,在编译完成之后,inner 实例内部会有指向 outer 实例的引用` this$0 ` ,但是简单的` outer.name ` 是无法访问 private 属性的。从反编译的结果可以看到,outer 中会有一个桥方法` static String access$000(OutterClass ) ` ,恰好返回 String 类型,即 userName 属性。正是通过这个方法实现内部类访问外部类私有属性。所以反编译后的` printOut() ` 方法大致如下:
415+ 实际上,在编译完成之后,inner 实例内部会有指向 outer 实例的引用` this$0 ` ,但是简单的` outer.name ` 是无法访问 private 属性的。从反编译的结果可以看到,outer 中会有一个桥方法` static String access$000(OuterClass ) ` ,恰好返回 String 类型,即 userName 属性。正是通过这个方法实现内部类访问外部类私有属性。所以反编译后的` printOut() ` 方法大致如下:
415416
416417``` java
417418public void printOut() {
418- System . out. println(" Username from OutterClass :" + OutterClass . access$000(this . this $0 ));
419+ System . out. println(" Username from OuterClass :" + OuterClass . access$000(this . this $0 ));
419420}
420421```
421422
@@ -426,7 +427,7 @@ public void printOut() {
4264273 . 匿名内部类、局部内部类通过复制使用局部变量,该变量初始化之后就不能被修改。以下是一个案例:
427428
428429``` java
429- public class OutterClass {
430+ public class OuterClass {
430431 private String userName;
431432
432433 public void test (){
@@ -447,10 +448,10 @@ public class OutterClass {
447448``` java
448449// javap命令反编译Inner的结果
449450// i被复制进内部类,且为final
450- class OutterClass $1Inner {
451+ class OuterClass $1Inner {
451452 final int val$i;
452- final OutterClass this $0 ;
453- OutterClass $1Inner ();
453+ final OuterClass this $0 ;
454+ OuterClass $1Inner ();
454455 public void printName ();
455456}
456457
@@ -701,7 +702,7 @@ public static transient void main(String args[])
701702 }
702703 else
703704 br. close();
704- break MISSING_BLOCK_LABEL_113 ;
705+ break MISSING_BLOCK_LABEL_113 ; // 该标签为反编译工具的生成错误,(不是Java语法本身的内容)属于反编译工具的临时占位符。正常情况下编译器生成的字节码不会包含这种无效标签。
705706 Exception exception;
706707 exception;
707708 if (br != null )
0 commit comments