4
回答
局部内部类初始化问题!!
华为云实践训练营,热门技术免费实践!>>>   
public class OutClass{
	
	private String name = "sa";
	private int id = 12;
	private String address = "jaxu";
	
	
	public void start(final String param){
	
		class innerClass{
			
			
			public void fun(){
				System.out.println(param);
				System.out.println(OutClass.this.name);
				System.out.println(OutClass.this.id);
				System.out.println(OutClass.this.address);
			}
		}
		
		new innerClass();
	
	}
	
	public static void main(String[] args){
		OutClass out = new OutClass();
		out.start("test");
	}
}

这是我简单编写的一段代码

然后我通过反编译,查看外部类和内部类的方法实现

外部类中的start方法中,new 一个内部类实例,要传递进去一个外部类的引用和start方法中的参数,咋一看没问题,局部内部类在实现使用外部类方法中的参数的时,就是这样操作的,但是我又看了下内部类的反编译

有一个自动生成的外部类引用,一个保存外部类start方法中的参数的域,没毛病,但是构造函数,为啥没有参数,而且通过构造方法内部反编译看得出,里面在设置,外部类的引用和保存start方法中参数的域的值,但是这两个参数从哪里获得来的,而且。从外部类start方法反编译看来,明明调用的方法是带有两个参数的构造方法。求大佬解释!

我通过反编译成员内部类,内部类构造方法是会添加一个参数,传递外部类引用的,局部内部类是怎么实现的

举报
0o涛涛o0
发帖于2个月前 4回/199阅

为什么我这边解析出来的是有的:

// Compiled from OutClass.java (version 1.7 : 51.0, super bit)
class OutClass$1innerClass {
  
  // Field descriptor #6 LOutClass;
  final synthetic OutClass this$0;
  
  // Field descriptor #8 Ljava/lang/String;
  private final synthetic java.lang.String val$param;
  
  // Method descriptor #10 (LOutClass;Ljava/lang/String;)V
  // Stack: 2, Locals: 3
  OutClass$1innerClass(OutClass arg0, java.lang.String arg1);
     0  aload_0 [this]
     1  aload_1 [arg0]
     2  putfield OutClass$1innerClass.this$0 : OutClass [12]
     5  aload_0 [this]
     6  aload_2 [arg1]
     7  putfield OutClass$1innerClass.val$param : java.lang.String [14]
    10  aload_0 [this]
    11  invokespecial java.lang.Object() [16]
    14  return
      Line numbers:
        [pc: 0, line: 9]
      Local variable table:
        [pc: 0, pc: 15] local: this index: 0 type: new OutClass(){}
  
  // Method descriptor #18 ()V
  // Stack: 2, Locals: 1
  public void fun();
     0  getstatic java.lang.System.out : java.io.PrintStream [24]
     3  aload_0 [this]
     4  getfield OutClass$1innerClass.val$param : java.lang.String [14]
     7  invokevirtual java.io.PrintStream.println(java.lang.String) : void [30]
    10  getstatic java.lang.System.out : java.io.PrintStream [24]
    13  aload_0 [this]
    14  getfield OutClass$1innerClass.this$0 : OutClass [12]
    17  invokestatic OutClass.access$0(OutClass) : java.lang.String [36]
    20  invokevirtual java.io.PrintStream.println(java.lang.String) : void [30]
    23  getstatic java.lang.System.out : java.io.PrintStream [24]
    26  aload_0 [this]
    27  getfield OutClass$1innerClass.this$0 : OutClass [12]
    30  invokestatic OutClass.access$1(OutClass) : int [42]
    33  invokevirtual java.io.PrintStream.println(int) : void [46]
    36  getstatic java.lang.System.out : java.io.PrintStream [24]
    39  aload_0 [this]
    40  getfield OutClass$1innerClass.this$0 : OutClass [12]
    43  invokestatic OutClass.access$2(OutClass) : java.lang.String [49]
    46  invokevirtual java.io.PrintStream.println(java.lang.String) : void [30]
    49  return
      Line numbers:
        [pc: 0, line: 12]
        [pc: 10, line: 13]
        [pc: 23, line: 14]
        [pc: 36, line: 15]
        [pc: 49, line: 16]
      Local variable table:
        [pc: 0, pc: 50] local: this index: 0 type: new OutClass(){}

  Inner classes:
    [inner class info: #1 OutClass$1innerClass, outer class info: #0
     inner name: #58 innerClass, accessflags: 0 default]
  Enclosing Method: #37  #55 OutClass.start(Ljava/lang/String;)V
}

--- 共有 1 条评论 ---
0o涛涛o0我的是jdk1.8,会是这个原因吗 2个月前 回复

给你JDK8的版本

// Compiled from OutClass.java (version 1.8 : 52.0, super bit)
class OutClass$1innerClass {
  
  // Field descriptor #6 LOutClass;
  final synthetic OutClass this$0;
  
  // Field descriptor #8 Ljava/lang/String;
  private final synthetic java.lang.String val$param;
  
  // Method descriptor #10 (LOutClass;Ljava/lang/String;)V
  // Stack: 2, Locals: 3
  OutClass$1innerClass(OutClass this$0, java.lang.String val$param);
     0  aload_0 [this]
     1  aload_1 [this$0]
     2  putfield OutClass$1innerClass.this$0 : OutClass [12]
     5  aload_0 [this]
     6  aload_2 [val$param]
     7  putfield OutClass$1innerClass.val$param : java.lang.String [14]
    10  aload_0 [this]
    11  invokespecial java.lang.Object() [16]
    14  return
      Line numbers:
        [pc: 0, line: 9]
      Local variable table:
        [pc: 0, pc: 15] local: this index: 0 type: new OutClass(){}
      Method Parameters:
        final mandated this$0
        final synthetic val$param
  
  // Method descriptor #18 ()V
  // Stack: 2, Locals: 1
  public void fun();
     0  getstatic java.lang.System.out : java.io.PrintStream [25]
     3  aload_0 [this]
     4  getfield OutClass$1innerClass.val$param : java.lang.String [14]
     7  invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]
    10  getstatic java.lang.System.out : java.io.PrintStream [25]
    13  aload_0 [this]
    14  getfield OutClass$1innerClass.this$0 : OutClass [12]
    17  invokestatic OutClass.access$0(OutClass) : java.lang.String [37]
    20  invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]
    23  getstatic java.lang.System.out : java.io.PrintStream [25]
    26  aload_0 [this]
    27  getfield OutClass$1innerClass.this$0 : OutClass [12]
    30  invokestatic OutClass.access$1(OutClass) : int [43]
    33  invokevirtual java.io.PrintStream.println(int) : void [47]
    36  getstatic java.lang.System.out : java.io.PrintStream [25]
    39  aload_0 [this]
    40  getfield OutClass$1innerClass.this$0 : OutClass [12]
    43  invokestatic OutClass.access$2(OutClass) : java.lang.String [50]
    46  invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]
    49  return
      Line numbers:
        [pc: 0, line: 12]
        [pc: 10, line: 13]
        [pc: 23, line: 14]
        [pc: 36, line: 15]
        [pc: 49, line: 16]
      Local variable table:
        [pc: 0, pc: 50] local: this index: 0 type: new OutClass(){}

  Inner classes:
    [inner class info: #1 OutClass$1innerClass, outer class info: #0
     inner name: #59 innerClass, accessflags: 0 default]
  Enclosing Method: #38  #56 OutClass.start(Ljava/lang/String;)V
}

--- 共有 1 条评论 ---
0o涛涛o0菜刀兄,我的这里依然局部内部类构造方法没有参数,不知道啥原因。。。。 2个月前 回复

依然没有参数

--- 共有 1 条评论 ---
依然菜刀额。。。。好吧。。。。不知道什么原因了。。。。。不管是用反编译工具,还是javap,还是Eclipse,我这边的结果都是一致的。。。。。 2个月前 回复

你说的没太看懂,本人菜鸟一枚,不过你说的内部类构造没有参数我是这么理解的

public void start(final String param){

 这句话表明你传过来的值是一个常量,该值是在常量池里;可以把param这个常量看成start的常量,而不是你局部内部类里面的,当你打印的时候,是直接打印这个常量,所以你局部内部类不需要进行初始化

至于

System.out.println(OutClass.this.name);
				System.out.println(OutClass.this.id);
				System.out.println(OutClass.this.address);
			}

name   id    address   这三个成员变量因为你没在局部内部类中定义,所以内部类当然就不用初始化赋值,它本身就没有这个成员啊,都是用的外部类的成员,内部类的最大特点是可以随意使用外部类的成员,你只要没在内部类中定义这些变量,最终调用的就会是你外部的成员变量,就近原则,内部有该变量调内部,没有掉方法的常量,方法没有调外部成员变量

他们不是继承关系,是类似于类和成员方法的关系

你想,你内部类没有定义这些变量,那它的构造也没东西让它去赋值

把内部类看成一个特殊的方法你就理解了,按照使用方法的思路来使用,

不知能不能解决你的问题,如果我的是错误的还请指出,也让我学习一下

顶部