用于实例化内部类的奇怪语法
在这个阶段,我没有想到我会在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抱怨什么,第二个版本在做什么?
背景信息: Button
和Button.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中调用一个方法时,你必须传递参数列表,即使它是空的。