双括号初始化 - 优点

8

我知道我们可以通过使用双括号初始化在Java中初始化集合。但是经过一些搜索发现,不建议使用它,因为它会有性能问题。

private static final Set<String> VALID_CODES = new HashSet<String>() {{
    add("XZ13s");
    add("AB21/X");
    add("YYLEX");
    add("AR2D");
 }};

我想知道,DOUBLE BRACE INITIALIZATION 有什么积极的方面或优势吗?


不,唯一的好处就是代码量少了..但对于那些不了解双括号初始化的人来说,它并不易读。 - Phani
2
虽然对于会编写Java的人来说更易读,在非静态上下文中,您将会获取到对封闭“this”的引用。当调用mutators时,您还可能会获取到对使用的final字段的固定引用。这对大多数Java程序员来说并不明显,可能会导致晦涩的内存问题。//无论如何,您应该编写类似于private static final Set<String> VALID_CODES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList("XZ13s", "AB21/X", "YYLEX", "AR2D")));的代码。 - Tom Hawtin - tackline
2个回答

6
不建议使用它,因为它存在性能问题。但我并没有看到任何性能问题。每当你看到有人说出于性能原因我做/没做某事时,你应该期望看到详细的分析比较替代方案,并解释其中一个如何满足特定的性能要求而另一个则不能。如果你没有看到这些,你可能会认为作者只是在猜测。
编辑:虽然我不得不承认每个类都需要一点时间来加载,但运行性能完全相同。我在这里演示了这一点:https://dev59.com/pnNA5IYBdhLWcg3wh-YC#14627268 如果你认为双花括号表示法更简单、更清晰,那么可以使用它。缺点是你改变了集合的类型,这可能会混淆那些不希望看到这种情况的函数,例如equals。
注意:正如Lukas Eder所指出的,如果你在非静态上下文中这样做,你需要小心。匿名子类集合将隐含地引用外部实例,如果它的生命周期长于集合,则会导致内存泄漏。你有没有想过可能会出现内存泄漏的情况?

1
问题“Java的双括号初始化的效率?”实际上是关于性能问题的,并且确实较慢。 - Alvin Wong
2
@AlvinWong 那个测试似乎相当有问题 - 特别是每当我看到一个测试返回“0毫秒”时,我的第一个猜测是代码尚未运行(在这种情况下完全合法,因为结果从未被使用)。此外,JVM没有正确预热... 我不会信任那些结果。 - assylias
1
它加载它们需要更长时间。如果您有1000个匿名类,那么无论如何都会出现问题,但即便如此,加载全部类需要额外的185毫秒,即每个类需要185微秒。如果您认为启动应用程序时的185微秒很重要,那么您可能会避免使用它们。 - Peter Lawrey
1
@RajaAsthana 如果你认为这更简单或更清晰,那就是品味问题了。;) 我有时会使用它,但也可能过度使用。 - Peter Lawrey
2
Peter,扩展HashMap/Set可能会强制进行类层次分析,除了需要进行IO之外。此外,加载类的成本并不总是微不足道的 - 比如,在多层类加载器结构中(应用程序服务器,特别是启用了RMI类加载器!),每个类加载器都委托给父级(必须这样做),通过JAR/文件系统搜索,回溯直到当前类加载器最终加载匿名类。再次强调,微基准测试并不足以证明一个案例。在我看来,“双括号”非常糟糕的实践。 - bestsss
显示剩余11条评论

3

没有特别的性能问题(除了通过类加载器加载类的成本 - 可以忽略不计)

以上内容确实创建了一个匿名类,因此它包含对周围实例的隐式this引用。这可能会对序列化框架造成一些困惑。例如,您序列化了创建的匿名类,突然发现您还尝试序列化包含的实例。

我想强调的是,在不同的框架和语言中(Scala-我在看你),匿名类可以在幕后大量使用。我从未听说过有人因为类加载而导致Scala性能出现问题。初始启动可能会稍微慢一点,但请记住JVM启动、JIT预热、任何网络访问等。

您可能会认为您的应用程序占用空间更大,因为类更多。我怀疑(再次)效果可以忽略不计(除非您将整个应用程序构建成匿名类!)


我们在哪里有一个匿名类? - Adam Arold
我回复了@Peter关于类加载的问题 - 它并不总是可以忽略不计。当然,成本是O(1),因为它仅在类初始化中使用。 - bestsss
除了序列化之外,我认为仅仅可能通过这种方式创建内存泄漏就更加严重了。 - Lukas Eder

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