我在其他地方读过静态匿名类没有意义 - 所有匿名类都应该绑定到封闭类型的实例。但编译器允许你这样做。这是一个例子:
class Test {
/*
* What's the difference at between
* Test.likeThis and Test.likeThat?
*/
// This is obviously okay:
private static final class LikeThat {
@Override
public String toString() { return "hello!"; }
}
public static Object likeThat = new LikeThat();
// What about this - is it really any different?
public static Object likeThis = new Object() {
@Override
public String toString() { return "hello!"; }
};
}
这里发生了什么?
答案 0 :(得分:7)
我认为静态匿名类没什么问题
答案 1 :(得分:7)
来自the Java Language Specification, section 8.1.3:
内部类 I 的实例,其声明发生在静态上下文中没有词法封闭的实例。但是,如果 I 立即在静态方法或静态初始化程序中声明,那么 I 确实有一个封闭块,这是词法最内层的块语句附上 I 的声明。
您的匿名类(likeThis
是一个实例)发生在静态上下文中,因此它不依赖于封闭的实例。但是,似乎它可以引用其封闭块的最终变量(参见8.1.3节的其余部分,它们给出了一个例子)。
顺便说一句,你的措辞有点欺骗性,你实际上指的是一个匿名类的静态实例(它是静态的实例,而不是类)。
答案 2 :(得分:5)
就像任何语言中的任何语言一样,你应该只考虑为什么你正在做的事情。如果您有很多这些实例,那么我会质疑设计决策,但这并不一定意味着它应该从不遵循。
当然,始终考虑课程的可测试性以及是否可以在需要时提供测试双重
答案 3 :(得分:1)
我认为他们没有任何意义。如果您不需要引用封闭对象,那么最好将其保持静态。之后它可以轻松地在单独的课堂上进化。
广泛的枚举习惯用法(Java 5之前的版本)使用与枚举类的匿名静态继承者类似的方法。可能现在,对于这种情况,现在最好坚持使用Java 5 enum
。
如果您能够为匿名静态类找到足够的实际应用程序 - 为什么不使用它们呢?
答案 4 :(得分:1)
我一直这样做。它对于实用程序接口的特殊情况实现尤其方便,例如:
/** A holder for {@link Thing}s. */
public interface ThingsHolder {
/** A {@link ThingsHolder} with nothing in it. */
public static final ThingsHolder EMPTY_HOLDER = new ThingsHolder() {
@Override
public Iterable<Thing> getThings() {
return Collections.emptySet();
}
};
/** Provides some things. */
Iterable<Thing> getThings();
}
您可以创建一个名为EmptyHolder
的私有静态内部类,并且在某些情况下可能会使代码更具可读性,但您没有理由 来执行此操作。
答案 5 :(得分:1)
根据引用JLS的this answer,匿名类从不 static
,但是当在“静态上下文”中创建时,它们没有“封闭实例”。 / p>
那就是说,
Test.this
(非静态变量this
无法从静态上下文引用),它们在编译时会出现相同的错误。Test$1
是“匿名类”而Test$LikeThat
是“成员类”。他们俩都有一个封闭的班级;它们都没有封闭的构造函数或方法。 (我只检查了看起来很可能的方法;可能还有其他差异。)
getModifiers()
,测试$ 1为static
,Test$LikeThat
为static final
!根据语言规范,Test$1
实际应为final
。嗯... 根据javap -c -verbose -s -private -l
,
Test$1
指定“EnclosingMethod”(可能是Test
的静态初始值设定项?)Test$LikeThat
在“InnerClass”(#12; //class Test$1
)和一个好奇的构造函数Test$LikeThat(Test$1)
下有一个额外的条目。这似乎发生,因为LikeThat
是private
,它构成了构造函数private
,因此编译器生成一个“trampoline”以允许从Test
调用它。如果删除private
,除了EnclosingMethod条目外,它们似乎编译成大致相同的东西。
Test$1
没有在非静态上下文中定义的字段final Test this$0;
。
答案 6 :(得分:0)
对我来说似乎完全合法。由于匿名类是static
,它不会引用任何封闭类,但不应该有任何恶意后果。
嗯,除了是一个隐藏的单身对象,这是非常邪恶的。
答案 7 :(得分:0)
当然他们不是。我总是使用静态嵌套类,除非我需要与封闭对象的隐式关联。
在java术语中嵌套类:=在另一个类(或接口)中声明的类。内部类是那些嵌套类,它们具有来自封闭类的关联实例。 (非静态成员类,本地类,匿名类)。
隐式关联有时可以防止垃圾收集。
答案 8 :(得分:-1)
这些可以非常方便,因为有可能做出循环引用:
class A
{
public static final A _1 = new A() {
public A foo()
{
return _2;
}
};
public static final A _2 = new A() {
public A foo()
{
return _1;
}
};
}
如果不使用匿名类,创建几个持有彼此引用的对象可能会非常尴尬。