简体   繁体   English

为什么 javac 允许“new CLS().new InnerCLS()”编译?

[英]Why does javac allow "new CLS().new InnerCLS()" compile?

Consider the following snippet:考虑以下片段:
(I came across this syntax when inspecting some decompiled class files and this is a minimal representation) (我在检查一些反编译的类文件时遇到了这个语法,这是一个最小的表示)

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

        System.out.println("Bye from " + o.getClass());
    }

    class Inner {}
}

This compiles and runs fine (I tested a bunch of JDKs).这编译并运行良好(我测试了一堆 JDK)。
Can someone please explain how come this compiles and what does this code represent?有人可以解释一下这是如何编译的以及这段代码代表什么吗?

This code creates 3 classes:这段代码创建了 3 个类:

1. Main - This creates the following code (I removed the irrelevant parts):   
    new Main$1
    dup
    new Main
    dup
    invokespecial Method Main <init> ()V
    dup
    invokevirtual Method java/lang/Object getClass ()Ljava/lang/Class;
    pop
    invokespecial Method Main$1 <init> (LMain;)V

Why is it calling getClass (the result is popped anyway)?

2. Main$Inner - This class looks like as would expect an inner class to look

3. Main$1 - This creates the following class (I removed the irrelevant parts):
    final class Main$1 extends Main$Inner 
    method <init> : (LMain;)V 
    aload_0
    aload_1
    dup
    invokevirtual Method java/lang/Object getClass ()Ljava/lang/Class;
    pop
    invokespecial Method Main$Inner <init> (LMain;)V
    return

Again, why is it calling getClass (the result is popped anyway)?

BTW, it can be nested even further like this:顺便说一句,它可以像这样进一步嵌套:

public class Main {
    public static void main(String[] args) {
        Object o = new Main().new Inner1().new Inner2().new Inner3() {};

        System.out.println("Bye from " + o.getClass());
    }

    class Inner1 {
        class Inner2 {
            class Inner3 {
            }
        }
    }
}

This is how instance (non-static) inner classes work.这就是实例(非静态)内部类的工作方式。 You need an instance of the outer class to instantiate instance of the inner class.您需要一个外部类的实例来实例化内部类的实例。 This is another example:这是另一个例子:

var outer = new Outer();
var inner = outer.new Outer.Inner();

See:看:

Inner classes must be instantiated with a this pointer to the outer class.内部类必须使用指向外部类的this指针进行实​​例化。

The syntax outer.new Inner() is one way to achieve that (the new instance of Inner will have the value of outer as the outer.this reference.语法outer.new Inner()是实现这一点的一种方式( Inner的新实例将把outer的值作为outer.this 引用。

This is equivalent to having a non-static method in the Main class:这相当于在 Main 类中有一个非静态方法:

class Main {

    Inner makeInner() {
        /// "this." is implied here, but it is there.
        return new Inner();
    }
    class Inner {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么Eclipse编译这个,但javac不编译? - Why does Eclipse compile this, but javac doesn't? 为什么当我的 IDE 没有时 javac 会抛出编译错误? - Why does javac throw compile errors when my IDE does not? 为什么 javac 允许一些不可能的强制转换而不是其他的? - Why does javac allow some impossible casts and not others? 为什么新的String(“”)编译而char c =''没有? - Why does new String(“”) compile while char c = '' does not? 为什么这个代码用eclipse编译器编译但不用javac编译(maven) - why does this code compile with eclipse compiler but not with javac (maven) 为什么 POJO 上的“final”会在带有内联 setter 的“new”上抛出编译错误? - Why does “final” on a POJO throw compile error on a “new” with inline setters? 为什么 Java 允许这段代码与 generics 一起编译? - Why does Java allow this code with generics to compile? 为什么添加“.map(a - > a)”允许这个编译? - Why does adding “.map(a -> a)” allow this to compile? Apache Ant {Compile javac srcdir}不存在 - Apache Ant {Compile javac srcdir} does not exist 为什么 javac 允许在类中使用它们的方法之后定义字段? - Why does javac allow fields to be defined after methods that use them in a class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM