实例化内部类的奇怪语法

发布于 2024-07-15 09:43:18 字数 683 浏览 6 评论 0原文

我没想到在这个阶段我会在 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 抱怨,它在第二个版本中做了什么?

背景信息:ButtonButton.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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

浅沫记忆 2024-07-22 09:43:18

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

该语法创建一个新的 Button.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 节 了解有关内部类和封闭实例的更多信息。

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 of 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 spec for more about inner classes and enclosing instances.

大海や 2024-07-22 09:43:18

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...

上课铃就是安魂曲 2024-07-22 09:43:18

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.

对你而言 2024-07-22 09:43:18

为了避免让自己和其他程序员对这个很少使用的功能感到困惑,您始终可以将内部类设为静态。

如果需要对外部类的引用,您可以在构造函数中显式传递它。

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.

残花月 2024-07-22 09:43:18

您实际上可以做到这一点,但您必须在 ButtonClickEvent 声明为 static >,然后使用语法就不会有任何问题:

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) {
    }
}

You actually can do that, but you have to declare ClickEvent as static inside Button, and then you shouldn't have any problem using you sintax:

buttonClick(new Button.ClickEvent(button));

Basically static makes the class ClickEvent belong directly to the class Button instead of a specific instance(i.e. new Button()) of Button.


Following @Jon Skeet example:

// 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) {
    }
}
眸中客 2024-07-22 09:43:18

您的代码将编译。

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

如果您输入而不是

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

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

Your code would compile, had you typed

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文