实例化内部类的奇怪语法
我没想到在这个阶段我会在 Java 中遇到全新的语法,但是你瞧,我刚刚遇到了一些东西:
确切的上下文和下面的代码应该做什么是相当不相关的 - 它只是为了给出某种上下文。
我试图在 IT Mill Toolkit 中综合创建一个事件,所以我写了这样的行:
buttonClick(new Button.ClickEvent(button));
但是,Eclipse 给了我以下错误消息:
没有可访问的 Button 类型的封闭实例。 必须使用 Button 类型的封闭实例来限定分配(例如 xnew A(),其中 x 是 Button 的实例)。
当我按如下方式重写上面的行时,它不再抱怨:
buttonClick(button.new ClickEvent(button)); // button instanceof Button
所以,我的问题是:后一个语法到底意味着什么,为什么第一个片段不起作用?什么是Java 抱怨,它在第二个版本中做了什么?
背景信息:Button
和 Button.ClickEvent
都是非抽象公共类。
I didn't imagine that I would encounter radically new syntax in Java anymore at this stage, but lo and behold, I just encountered something:
The exact context and what the code below should do is pretty irrelevant - it's there just to give some kind of context.
I'm trying to synthetically create an event in IT Mill Toolkit, so I wrote this kind of line:
buttonClick(new Button.ClickEvent(button));
But, Eclipse gives me the following error message:
No enclosing instance of type Button is accessible. Must qualify the allocation with an enclosing instance of type Button (e.g. x.new A() where x is an instance of Button).
When I rewrite the line above as follows, it doesn't complain anymore:
buttonClick(button.new ClickEvent(button)); // button instanceof Button
So, my question is: What does the latter syntax mean, exactly, and why doesn't the first snippet work? What is Java complaining about, and what's it doing in the second version?
Background info: Both Button
and Button.ClickEvent
are non-abstract public classes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
内部类(如
Button.ClickEvent
)需要对外部类(Button
)实例的引用。该语法创建一个新的
Button.ClickEvent
实例,并将其外部类引用设置为button
的值。这是一个例子 - 忽略缺乏封装等,它只是为了演示的目的:
请参阅 规范的第 8.1.3 节 了解有关内部类和封闭实例的更多信息。
Inner classes (like
Button.ClickEvent
) need a reference to an instance of the outer class (Button
).That syntax creates a new instance of
Button.ClickEvent
with its outer class reference set to the value ofbutton
.Here's an example - ignore the lack of encapsulation etc, it's just for the purposes of demonstration:
See section 8.1.3 of the spec for more about inner classes and enclosing instances.
Button.ClickEvent 是一个非静态内部类,因此该类的实例只能存在于 Button 实例中。
在您的第二个代码示例中,您有一个 Button 实例,并创建了一个包含在此 Button 实例中的 ClickEvent 实例...
Button.ClickEvent is a non-static inner class so an instance of this class can only exist enclosed in a instance of Button.
In your second code example you have an instance of Button and you create an instance of ClickEvent enclosed in this Button instance...
Java 中的非静态内部类包含一个隐藏引用,该引用指向声明它的外部类的实例。因此,您最初收到的错误消息是告诉您,如果不指定内部类,则无法创建内部类的新实例要附加到的外部类的实例。
也许您以前没有见过该语法的原因是内部类通常在外部类的方法中分配,编译器会自动处理这个问题。
A non-static inner class in Java contains a hidden reference that points to an instance of the outer class it is declared in. So the error message you got originally is telling you that you cannot create a new instance of the inner class without also specifying an instance of the outer class for it to be attached to.
Perhaps the reason you haven't seen that syntax before is that inner classes are often allocated in a method of the outer class, where the compiler takes care of this automatically.
为了避免让自己和其他程序员对这个很少使用的功能感到困惑,您始终可以将内部类设为静态。
如果需要对外部类的引用,您可以在构造函数中显式传递它。
To avoid confusing yourself and fellow programmers with this rarely-used feature you can always make inner classes static.
In case a reference to the outer class is needed you can pass it explicitly in the constructor.
您实际上可以做到这一点,但您必须在
Button
ClickEvent
声明为static
>,然后使用语法就不会有任何问题:基本上
static
使类ClickEvent
直接属于类Button
而不是Button
的特定实例(即new Button()
)。以下@Jon Skeet 为例:
You actually can do that, but you have to declare
ClickEvent
asstatic
insideButton
, and then you shouldn't have any problem using you sintax:Basically
static
makes the classClickEvent
belong directly to the classButton
instead of a specific instance(i.e.new Button()
) ofButton
.Following @Jon Skeet example:
您的代码将编译。
如果您输入而不是
buttonClick(new Button.ClickEvent(button)); ,
因为构造函数是一种方法,当您在 Java 中调用方法时,您必须传递参数列表,即使它是空的。
Your code would compile, had you typed
instead of
buttonClick(new Button.ClickEvent(button));
as a constructor is a method and when you call a method in Java you must pass the list of arguments, even when it is empty.