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

为什么javac允许“new CLS().new InnerCLS()”编译?,java,javac,Java,Javac,考虑以下代码段: 我在检查一些反编译的类文件时遇到了这种语法,这是一种最小的表示 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 {} } 这可以很好地编译

考虑以下代码段: 我在检查一些反编译的类文件时遇到了这种语法,这是一种最小的表示

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 {}
}
这可以很好地编译和运行,我测试了很多JDK。 有人能解释一下这是怎么编译的,这段代码代表什么吗

此代码创建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)?

这就是实例非静态内部类的工作方式。您需要外部类的实例来实例化内部类的实例。这是另一个例子:

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


这就是实例非静态内部类的工作方式。您需要外部类的实例来实例化内部类的实例。这是另一个例子:

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


内部类必须用指向外部类的this指针实例化

语法outer.new-Inner是实现Inner的新实例将值outer作为outer.this引用的一种方法

这相当于在主类中有一个非静态方法:

class Main {

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

内部类必须用指向外部类的this指针实例化

语法outer.new-Inner是实现Inner的新实例将值outer作为outer.this引用的一种方法

这相当于在主类中有一个非静态方法:

class Main {

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

为什么不编译呢?内部类是一个有效类。您是在询问新的CLS.new InnerCLS,正如您的标题所示,还是在询问它后面的{}?@sepp2k我是在询问新的CLS.new InnerCLS。如果{}与您的问题无关,为什么要在代码中包含它“从什么时候开始写.new是有效的?”因为Java 1.1引入了内部类。@EliFinkel非静态内部类与静态成员非常不同。它们只能通过实例访问。为什么不编译?内部类是一个有效类。您是在询问新的CLS.new InnerCLS,正如您的标题所示,还是在询问它后面的{}?@sepp2k我是在询问新的CLS.new InnerCLS。如果{}与您的问题无关,为什么要在代码中包含它“从什么时候开始写.new是有效的?”因为Java 1.1引入了内部类。@EliFinkel非静态内部类与静态成员非常不同。只能通过实例访问它们。确定。你能给我指一些文件吗?另外,为什么要调用getClass?getClass在System.out.println行中调用。调用可能只是为了证明您有一个内部类的实例,并且它的基础名称是Main$Inner.Nope。如您所见,getClass在Main$1的构造函数中被调用。你能给我指一些文件吗?另外,为什么要调用getClass?getClass在System.out.println行中调用。调用可能只是为了证明您有一个内部类的实例,并且它的基础名称是Main$Inner.Nope。如您所见,getClass在Main$1的构造函数中被调用,您知道getClass似乎不必要的调用吗?我不确定,但可能是因为额外的{};在赋值表达式的末尾,我相信它创建了匿名类:它在没有{}的情况下发生,我想我已经弄明白了。getClass调用是为了使像Outernull.new internal这样的快速调用失败,而不是让它们以后以一种不太明显的方式失败,类似于隐式程序集生成的空指针检查。您知道getClass似乎不必要的调用吗?我不确定,但可能是因为额外的{};在赋值表达式的末尾,我相信它创建了匿名类:它在没有{}的情况下发生,我想我已经弄明白了。getClass调用是使像Outernull.new internal这样的快速调用失败,而不是让它们稍后以一种不太明显的方式失败,类似于隐式程序集生成的空指针检查。