带有以下双括号的构造函数调用是什么?

发布于 2024-07-26 05:59:43 字数 838 浏览 9 评论 0原文

不幸的是,我已经大约五年没有编写 Java 代码了,我完全不记得下面的代码是如何或为什么工作的。

我偶然发现了一个类似的例子并将其分解为这样。 重点是注释下面的部分:我没有得到构造函数符号后跟双括号中的块。 不幸的是,我在 Java 文档中或通过 Google 找不到任何内容(我应该用 google 搜索什么词?)。

package syntaxtest;

public class Main {

    public static void main(String[] args) {

        // What kind of notation is this?
        MyTest tester = new MyTest() {{
            setName("John Johnson");
        }};

        System.out.println(tester.getName());
    }
}


class MyTest {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

所以这是我的问题:

  1. 这个符号/语法是如何调用的?
  2. 我在哪里可以阅读有关它的一些文档?

我想/希望如果有人能为我提供第一个问题的答案,我将能够自己回答第二个问题。

明确地说:我知道输出是 John Johnson ;)但我不知道它为什么起作用。

Unfortunately I haven't coded Java for about five years and I absolutely can not remember how or why the following code is working.

I stumbled across a similar example and broke it down to this. The emphasis is on the part below the comment: I don't get the constructor notation followed by the block in double brackets. And unfortunately I can not find anything in the Java documentation or by using Google (what word(s) should I google?).

package syntaxtest;

public class Main {

    public static void main(String[] args) {

        // What kind of notation is this?
        MyTest tester = new MyTest() {{
            setName("John Johnson");
        }};

        System.out.println(tester.getName());
    }
}


class MyTest {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

So here are my questions:

  1. How is this notation/syntax called?
  2. Where can I read some documentation about it?

I guess/ hope I will be able to answer the second question by myself if somebody can provide me with the answer to the first question.

To make it clear: I know the output is John Johnson ;) But I don't know why it is working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(3

浅黛梨妆こ 2024-08-02 05:59:43

这称为双括号初始化

第一个大括号创建一个新的
匿名内部类,第二个
声明一个实例初始化块
当匿名内部运行时
类被实例化。 这类
初始化块被正式调用
一个“实例初始值设定项”,因为它
在实例范围内声明
类的——“静态初始化器”
是一个相关的概念,其中
关键字 static 放在前面
开始块的大括号,以及
尽快在班级级别执行
当类加载器完成加载时
类(指定于
http://java.sun.com/docs/books /jls/third_edition/html/classes.html#8.6)
初始化块可以使用任何
方法、字段和最终变量
在包含范围内可用,但是
人们必须警惕这样一个事实:
初始化程序在之前运行
构造函数。

这只适用于非最终版本
类,因为它创建了一个
匿名子类。

This is known as double brace initialization:

The first brace creates a new
AnonymousInnerClass, the second
declares an instance initializer block
that is run when the anonymous inner
class is instantiated. This type of
initializer block is formally called
an "instance initializer", because it
is declared within the instance scope
of the class -- "static initializers"
are a related concept where the
keyword static is placed before the
brace that starts the block, and which
is executed at the class level as soon
as the classloader completes loading
the class (specified at
http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6)
The initializer block can use any
methods, fields and final variables
available in the containing scope, but
one has to be wary of the fact that
initializers are run before
constructors.

This only works only for non-final
classes because it creates an
anonymous subclass.

月亮坠入山谷 2024-08-02 05:59:43

让我们稍微不同地布局代码:

MyTest tester = new MyTest() {
  {
    setName("John Johnson");
  }
};

您在这里看到的称为双大括号初始化。 您有一个 MyTest 类的匿名内部子类,以及一个初始化块,该块包含构造对象时运行的代码。

通常,您会将此类代码放入构造函数中,但由于匿名内部类不能具有构造函数,因此这是保证代码在预期时运行的唯一方法。

话虽如此,这样做有点难看。 还有更好的方法。 然而,我自己有时也会使用它,通常是在以下习惯用法中创建一个不可变的映射:

final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
    put("one", 1);
    put("two", 2);
    // etc
}});

创建一个新的映射,覆盖它,在初始化块中向它添加一些值,并将其包装在一个不可修改的映射中。

Let's layout the code a bit differently:

MyTest tester = new MyTest() {
  {
    setName("John Johnson");
  }
};

What you see here is called double brace initialization. You have an anonymous inner subclass of class MyTest, along with an initializer block, which is a block that contains code that is run when the object is constructed.

Normally, you would put such code in the constructor, but since anonymous inner classes can't have constructors, this is the only way to guarantee the code is run when it's supposed to.

Having said that, it's a bit ugly to do this. There are better ways. However, I do use it myself on occasion, usually in the following idiom to create an immutable map:

final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
    put("one", 1);
    put("two", 2);
    // etc
}});

Which creates a new map, overrides it, adds some values to it in the initializer block, and wraps it in an unmodifiable map.

网白 2024-08-02 05:59:43
MyTest tester = new MyTest() {{
   setName("John Johnson");
}};

是相同的

MyTest tester = new MyTest();
tester.setName("John Johnson");
MyTest tester = new MyTest() {{
   setName("John Johnson");
}};

is the same as

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