java 实例化内部类的奇怪语法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/633585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Strange syntax for instantiating an inner class
提问by Henrik Paul
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:
我没想到在这个阶段我会在 Java 中遇到全新的语法,但是瞧,我刚刚遇到了一些事情:
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:
我试图在 IT Mill Toolkit 中综合创建一个事件,所以我写了这样一行:
buttonClick(new Button.ClickEvent(button));
But, Eclipse gives me the following error message:
但是,Eclipse 给了我以下错误消息:
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).
不能访问 Button 类型的封闭实例。必须使用 Button 类型的封闭实例限定分配(例如 xnew A(),其中 x 是 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?
所以,我的问题是:后一种语法究竟是什么意思,为什么第一个片段不起作用?Java 在抱怨什么,它在第二个版本中做了什么?
Background info: Both Buttonand Button.ClickEventare non-abstract public classes.
背景信息:Button和Button.ClickEvent都是非抽象公共类。
回答by Jon Skeet
Inner classes (like Button.ClickEvent) need a reference to an instance of the outer class (Button).
内部类(如Button.ClickEvent)需要对外部类 ( Button)的实例的引用。
That syntax creates a new instance of Button.ClickEventwith its outer class reference set to the value of button.
该语法创建了一个新实例,Button.ClickEvent其外部类引用设置为值button。
Here's an example - ignore the lack of encapsulation etc, it's just for the purposes of demonstration:
这是一个例子 - 忽略缺少封装等,仅用于演示目的:
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();
}
}
See section 8.1.3 of the specfor more about inner classes and enclosing instances.
有关内部类和封闭实例的更多信息,请参阅规范的第 8.1.3 节。
回答by pgras
Button.ClickEvent is a non-static inner class so an instance of this class can only exist enclosed in a instance of Button.
Button.ClickEvent 是一个非静态内部类,因此此类的实例只能存在于包含在 Button 实例中。
In your second code example you have an instance of Button and you create an instance of ClickEvent enclosed in this Button instance...
在您的第二个代码示例中,您有一个 Button 实例,并创建了一个包含在此 Button 实例中的 ClickEvent 实例...
回答by Daniel Earwicker
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.
Java 中的非静态内部类包含一个隐藏引用,该引用指向在其中声明它的外部类的实例。因此,您最初收到的错误消息告诉您,如果不指定,则无法创建内部类的新实例要附加到的外部类的实例。
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.
也许您之前没有见过这种语法的原因是内部类通常在外部类的方法中分配,编译器会自动处理这个。
回答by starblue
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.
如果需要对外部类的引用,您可以在构造函数中显式传递它。
回答by toto_tico
You actually can do that, but you have to declare ClickEventas staticinside Button, and then you shouldn't have any problem using you sintax:
你实际上可以做到这一点,但你必须声明ClickEvent为staticinside Button,然后你使用 sintax 应该没有任何问题:
buttonClick(new Button.ClickEvent(button));
Basically staticmakes the class ClickEventbelong directly to the class Buttoninstead of a specific instance(i.e. new Button()) of Button.
基本上static使类ClickEvent属于直接的类Button,而不是一个特定的实例(即new Button()的)Button。
Following @Jon Skeet example:
以下@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) {
}
}
回答by diginoise
Your code would compile, had you typed
你的代码会编译,如果你输入
buttonClick(new Button().ClickEvent(button));
instead of
代替
buttonClick(new Button.ClickEvent(button));
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.
因为构造函数是一个方法,当你在 Java 中调用一个方法时,你必须传递参数列表,即使它是空的。

