【问题标题】:Does string constant pool works with singleton annotated variables too?字符串常量池是否也适用于单例注释变量?
【发布时间】:2021-08-03 04:38:33
【问题描述】:
object Keys {
    @Singleton
    const val KEY_Q = "question"
    @Singleton
    const val KEY_ID = "quesid"
}

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

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

【问题讨论】:

  • 注释无关。字符串文字总是在池中。
  • 会占用同样多的内存吗?实际上,我希望每次都使用相同的变量,而不是创建相同的新引用。这里可以吗?
  • 1) 内存量也无关紧要。 2)你有 3 个不同的变量,所以很明显将使用 3 个变量。但这是你的意思吗?变量和值是不同的东西。
  • 你想多了。这里的字符串每个可能占用 30 或 40 个字节。您的整个程序可能使用数百万……甚至数十亿字节。 30 或 40 个字节“浪费”(在单例上)绝对没有区别。继续。想想一个真正重要的问题......
  • 先生,这对我很重要。我刚刚分享了一个较小的代码块。我想澄清我对此的疑问。能回答就好了。

标签: java android singleton


【解决方案1】:

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

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

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

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

然而……

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

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

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

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

  • 最后,从 Java 9 开始,GC 对在几个 GC 周期中幸存下来的字符串执行自动字符串重复数据删除。所以如果你真的有很多重复的字符串数据,最好的解决办法就是让GC来处理。


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

【讨论】:

  • 因此,将@Singleton Annotation 与 const 字符串变量一起使用没有任何好处!
  • 如果你这样做只是为了节省内存,没有任何好处。而且即使有好处,也只是微不足道,完全浪费了程序员的时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 2012-12-18
  • 2014-06-08
  • 1970-01-01
  • 2017-01-06
  • 1970-01-01
相关资源
最近更新 更多