双括号初始化和“某种”静态匿名类

3

有时候为了测试,我会使用快速“双括号”初始化方法,在Outer类中创建匿名嵌套类,例如:

static final Set<String> sSet1 = new HashSet<String>() {
    {
        add("string1");
        add("string2");
        // ...
    }
};

编辑 我正在纠正之前错误的陈述,即此示例保留对Outer实例的引用。它不是这样的,它实际上相当于以下内容:

static final Set<String> sSet2;
static {
    sSet2 = new HashSet<String>() {
        {
            add("string1");
            add("string2");
            // ...
        }
    };
}

两个变量sSet1sSet2都使用匿名嵌套类初始化,这些类没有保留对Outer类的引用。

这是否意味着这些匿名类实质上是静态嵌套类?


你的第一个示例没有引用“Outer”,还是我漏看了什么? - Sotirios Delimanolis
@SotiriosDelimanolis 嗯,我相信第一个示例中的匿名内部类确实包含对 Outer.this 的隐式引用。 - kiruwka
1
不,它不会。在两种情况下,您都处于“静态”上下文中。没有外部实例。 - Sotirios Delimanolis
@SotiriosDelimanolis 对,我太蠢了,抱歉。 - kiruwka
哈哈,那有点严厉了。通常我会在我的IDE中尝试这个Outer.this.someMethod()。如果不能编译,那就得重新思考我的逻辑了。 - Sotirios Delimanolis
@SotiriosDelimanolis 没错,你说得对,我在发帖之前应该先编译。我只是将尚未经过适当验证的想法放入一个问题中。 - kiruwka
1个回答

3
正如你所提到的相关问题所讨论的那样,匿名类在技术上不能是静态的,但如果它在静态上下文中声明,也就是说它没有对外部实例的引用,它可以被称为有效静态
然而,在你的情况下,两种方法之间绝对没有区别,因为静态字段的初始化也是在静态上下文中进行的。

+1 是的,你关于没有区别是正确的,我完全忽略了这一点。你能否请给出“有效静态(effectively static)”与普通“静态嵌套(static nested)”类之间的一些实际区别呢?Tom在他的答案中引用了《JLS第3版》(我也参考了他的回答),但也许你能为我简单概括一下吗?谢谢。 - kiruwka
阅读了所有关于这个问题的回答后,我意识到除了不建议使用这个Java特性可能会被取消之外,实际上并没有技术上的区别。 - kiruwka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接