【问题标题】:Using static variables for Strings对字符串使用静态变量
【发布时间】:2011-02-17 14:59:31
【问题描述】:

以下内容取自 Best practice: Writing efficient code 但我不明白为什么

private static String x = "example";

快于

private static final String x ="example";

谁能解释一下。

对字符串使用静态变量

当您定义静态字段时(也 称为类字段)类型的字符串, 您可以通过以下方式提高应用程序速度 使用静态变量(非最终变量) 而不是常量(最终)。这 原始数据则相反 类型,例如 int。

例如,您可以创建一个字符串 对象如下:

private static final String x = "example";

对于这个静态常量(表示为 最后的关键字),每次你 使用常量,一个临时字符串 创建实例。编译器 消除“x”并将其替换为 字节码中的字符串“example”, 以便 BlackBerry® Java® Virtual 机器执行哈希表查找 每次引用“x”时。

相反,对于静态变量(无 final 关键字),创建字符串 一次。 BlackBerry JVM 执行 哈希表查找仅当它 初始化“x”,因此访问速度更快。

private static String x = "example";

您可以使用公共常量(即 最终字段),但您必须标记 变量作为私有变量。

【问题讨论】:

    标签: java blackberry


    【解决方案1】:

    文字解释了它,只需阅读它。

    但要改写它: 它更快,因为它是。 黑莓 jvm 使用非最终版本的方式更好。 之所以这样,是因为它以这种方式设计

    【讨论】:

    • 对于这个静态常量(用final关键字表示),每次使用该常量时,都会创建一个临时的String实例。为什么??
    • @Vivart:因为 BlackBerry OS 上使用的 JVM 就是这样设计的。没有别的原因!这是一个实现细节,任何 JVM 实现都可以选择使用这种或其他方式,只要它符合规范即可。规范中没有规定final 字段必须比非final 字段快。
    • 感谢您在阅读该文档后的回复,我对发生了什么感到困惑。
    【解决方案2】:

    有一个运行时字符串文字池。当您将字符串创建为 Final 时,JVM 会在您每次使用该字符串时创建一个副本。当字符串不是最终的时,它会在您第一次创建它时插入到字符串文字池中,然后从池中查找它,这样可以避免字符串的副本。

    【讨论】:

      【解决方案3】:

      这是黑莓虚拟机的细节。其他虚拟机可能会采取不同的方式。

      旁注:在真正遇到性能问题之前不要过多关注优化(这称为“过早优化”),因为如果这样做,很可能会在您所在的地方泄漏性能没想到会这样。

      【讨论】:

      • 关于“其他虚拟机可能会做不同的事情”:我什至会说大多数其他虚拟机几乎肯定会做不同的事情。此特定建议专门适用于 BlackBerry VM,并且不应被视为普遍适用。
      • @Joachim:很高兴知道。当我第一次阅读这个问题时,我正在翻转。至少这种讽刺仅限于黑莓虚拟机。
      【解决方案4】:

      我不知道这一点,但这对我来说很有意义:

      JVM 有一个内部字符串文字缓存。每次使用文字创建字符串时,JVM 都必须在缓存中查找它,如果不存在,则存储它。

      现在编译器可以用字符串字面量内联 final 变量,因为它在编译时是已知的,而且这似乎是提高性能的好主意。

      所以你的代码:

      static final String CONST = "myconst";
      ...
      if (CONST.equals(aVar))
      ...
      case CONST
      ...
      

      由编译器重写为:

      static final String CONST = "myconst";
      ...
      if ("myconst".equals(aVar))
      ...
      case "myconst"
      ...
      

      如果 JVM 实现不够聪明,在这个例子中它需要查找“myconst” 3 次。

      当您不将 CONST 标记为“final”时,编译器无法“优化”它,因为变量可以在运行时更改。您的代码将被 1:1 编译,JVM 只需要在变量中查找 Object。

      顺便说一句:糟糕的 JVM 实现不应该定义您的编码风格。 “final” 提供了很多安全性,只要它不会真正影响您的性能:不要关心它是提高还是降低您的速度 - 无论如何,对于下一个 JVM 来说它是不同的

      【讨论】:

      • 也许您应该澄清这里所讨论的“JVM”是 Blackberry 的“JVM”实现。据我所知,Oracle JVM(如果他们在这方面遵循 OpenJDK,也就是说)将静态最终字符串内部化,并将它们放入 PermGen,只要有对它们的引用。这使得查找 O(1) 而不是上述结果的 O(n)(在比较中)
      • @Steen Oracle JVM 也有一个字符串文字缓存。您所描述的是此缓存的内部实现。每个 JVM 都需要一个,因为没有它String.intern() 和其他东西就无法工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 2011-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多