首页 > 解决方案 > 字符串常量池是否也适用于单例注释变量?

问题描述

object Keys {
    @Singleton
    const val KEY_Q = "question"
    @Singleton
    const val KEY_ID = "quesid"
}

我在我的单例类中使用带有许多字符串变量的单例注释。我想问一下,默认情况下,字符串变量存储在常量字符串池中,并且在更新过程中,JVM会在字符串池中检查相同的变量是否可用,如果是,则返回相同的引用创建一个新的。

正如我们在图片中看到的

现在我想问一下,当我们对字符串变量使用单例注释时,这个过程是否同样有效。如果是的话,那么使用带有这些带有不同变量的注释的类对我有什么好处。我是单身新手,请详细描述。谢谢

标签: javaandroidsingleton

解决方案


注解对 Java 中的字符串池行为没有影响。如果您的示例是 Java,则@Singleton注释不会节省内存1

有一个非常简单的规则涵盖了进入 Java 字符串池的内容。

  • 如果字符串是评估编译时常量表达式的结果,则将单个副本放置在字符串池中。JLS 指定编译时常量表达式是什么2

  • 字符串进入字符串池3唯一其他情况是某些代码显式调用它。intern

然而 ...

在现代硬件上的现代JVM 中,字符串是否进入字符串池很可能无关紧要。

  • 字符串池是堆的一部分,像堆的其余部分一样被垃圾收集。

  • 与应用程序的其余内存使用相比,每个单独的字符串文字占用的空间很可能是微不足道的。几个字节,与兆字节......或千兆字节相比。

  • 如果你认为你可以intern使用字符串并利用字符串池中字符串的特殊属性(通过==比较字符串),那么你就是在非常危险的地方。这是一个微优化......只有当你可以确定你已经实习了所有的字符串时它才有效。(此外,实习比一些字符串比较更昂贵,因此您的优化尝试可能会失败。)

  • 最后,从 Java 9 开始,GC 对经过几个 GC 周期的字符串执行自动字符串重复数据删除。所以如果你确实有很多重复的字符串数据,最好的解决方案是让 GC 处理它。


1 - 我无法准确告诉您这对您的示例意味着什么,因为您使用的语法不是有效的 Java。Java 没有const,valobject关键字。这看起来像 Kotlin。
2 - 常见的例子是字符串文字或字符串文字的串联但还有其他的;见JLS 15.28
3 - 字符串本身或字符串的副本是否进入池取决于实现。但是应用程序很难区分不同的行为。


推荐阅读