java - 为什么我们为内部类创建对象时会调用getClass()?

标签 java bytecode inner-classes

我正在研究内部类及其字节码内部的工作原理,我正在跟踪堆栈,但不明白为什么要调用 getClass()?
我找到了一个 similar question for Lambda function但无法理解。

我确实试图理解没有空检查是必需的,在 JDK 8 之后它被一个名为 requiredNoNull 的静态函数所取代。

代码:

class Outer{
      class Inner{
      }
      public static void main(String args[]){
            Outer.Inner obj = new Outer().new Inner();
      } 
}

字节码:

 public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class Outer$Inner
       3: dup
       4: new           #3                  // class Outer
       7: dup
       8: invokespecial #4                  // Method "<init>":()V
      11: dup
      12: invokevirtual #5                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
      15: pop
      16: invokespecial #6                  // Method Outer$Inner."<init>":(LOuter;)V
      19: astore_1

最佳答案

It's a null check in disguise ,仅此而已。不过,在那种特殊情况下,它并不是真正需要的, future 的 javac 会对其进行一些优化 - 请看下面的示例。

可能这会更好地解释问题(使用 java-12,其中 getClass hack 已被 Objects::requireNonNull 取代):

public class Outer {

    class Inner {

    }

    public void left() {
        Outer.Inner inner = new Outer().new Inner();
    }

    public void right(Outer outer) {
        Outer.Inner inner = outer.new Inner();
    }
}

left 方法将编译为使用Objects::requireNonNull 的内容(您可以自己查看字节码),因为Outer 的创建发生在适当的位置,编译器可以确定 new Outer() 实例不是 null

另一方面,当您将 Outer 作为参数传递时,编译器无法证明传递的实例肯定不是 null,因此 Objects::requireNonNull 将出现在字节码中。

关于java - 为什么我们为内部类创建对象时会调用getClass()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56881751/

相关文章:

python - 在 Python 中更改对运行时函数的引用

Java 代码显示错误 : "inner class can' t be public"?

scala - 是否有像Javassist这样的Scala感知高级字节码操作工具?

java - 错误 : String types not allowed (at 'layout_height' with value 'wrap content' ). activity_main.xml

java - 在 Java 中将 HashMap.toString() 转换回 HashMap

java - 使用正则表达式提取括号中的数字

java - 有什么方法可以从字节码重新生成堆栈图?

java - 构造函数中的方法?

c++ - 在父类内部定义子类的子结构

java - UrlEncodedFormEntity 替换