用于实例化内部类的奇怪语法

在这个阶段,我没有想到我会在Java中遇到全新的语法,但是你看,我刚刚遇到了一些事情:

确切的上下文和下面的代码应该做什么是非常不相干的 – 它只是为了给某种上下文。

我试图在IT Mill Toolkit中综合创build一个事件,所以我写了这样一行:

buttonClick(new Button.ClickEvent(button)); 

但是,Eclipse给我以下错误信息:

没有封闭types的Button实例可以访问。 必须使用封闭的Buttontypes实例来限定分配(egxnew A(),其中x是Button的一个实例)。

当我重写上面的行,如下所示,它不再抱怨:

 buttonClick(button.new ClickEvent(button)); // button instanceof Button 

所以,我的问题是: 后面的语法究竟什么意思,为什么不是第一个片段的工作? Java抱怨什么,第二个版本在做什么?

背景信息: ButtonButton.ClickEvent都是非抽象的公共类。

内部类(如Button.ClickEvent )需要对外部类( Button )的实例的引用。

该语法创buildButton.ClickEvent的新实例,其外部类参考设置为button的值。

这是一个例子 – 忽略封装等的缺乏,这只是为了演示的目的:

 class Outer { String name; class Inner { void sayHi() { System.out.println("Outer name = " + name); } } } public class Test { public static void main(String[] args) { Outer outer = new Outer(); outer.name = "Fred"; Outer.Inner inner = outer.new Inner(); inner.sayHi(); } } 

有关内部类和封闭实例的更多信息,请参见规范的第8.1.3节 。

Button.ClickEvent是一个非静态的内部类,所以这个类的实例只能存在于Button的一个实例中。

在你的第二个代码示例中,你有一个Button的实例,并且创build一个封闭在这个Button实例中的ClickEvent实例。

Java中的一个非静态的内部类包含一个隐藏的引用,指向它声明的外部类的一个实例。所以你最初得到的错误信息告诉你,你不能创build一个新的内部类的实例,也没有指定它要附加到的外部类的实例。

也许你之前没有看到这个语法的原因是,内部类通常被分配在外部类的方法中,编译器自动处理这个方法。

为了避免让自己和程序员感到困惑,你可以使内部类静态化。

如果需要引用外部类,则可以在构造函数中明确地传递它。

你实际上可以做到这一点 ,但是你必须在Button声明ClickEvent static ,然后你不应该有任何问题使用你sintax:

 buttonClick(new Button.ClickEvent(button)); 

基本上static使得类ClickEvent直接属于类Button而不是Button的一个特定的实例(即new Button() )。


继@Jon Skeet例子:

 // Button.java class Button { public static class ClickEvent { public ClickEvent(Button b) { System.out.println("Instance: " + this.toString()); } } } // Test.java public class Test { public static void main(String[] args) { Button button = new Button(); buttonClick(new Button.ClickEvent(button)); } public static void buttonClick (Button.ClickEvent ce) { } } 

你的代码会编译,你input

 buttonClick(new Button().ClickEvent(button)); 

代替

buttonClick(new Button.ClickEvent(button));

作为构造函数是一种方法,当你在Java中调用一个方法时,你必须传递参数列表,即使它是空的。