【问题标题】:Does concatenating strings in Java always lead to new strings being created in memory?在 Java 中连接字符串是否总是会导致在内存中创建新字符串?
【发布时间】:2012-08-12 22:13:59
【问题描述】:

我有一个不适合屏幕宽度的长字符串。例如。

String longString = "This string is very long. It does not fit the width of the screen. So you have to scroll horizontally to read the whole string. This is very inconvenient indeed.";

为了方便阅读,我想到了这样写——

String longString = "This string is very long." + 
                    "It does not fit the width of the screen." +
                    "So you have to scroll horizontally" +
                    "to read the whole string." +
                    "This is very inconvenient indeed.";

但是,我意识到第二种方法使用字符串连接,并且会在内存中创建 5 个新字符串,这可能会导致性能下降。是这样吗?或者编译器是否足够聪明,可以找出我真正需要的只是一个字符串?我怎么能避免这样做呢?

【问题讨论】:

    标签: java string compiler-construction string-concatenation


    【解决方案1】:

    我意识到第二种方式使用字符串连接,会在内存中创建 5 个新字符串,这可能会导致性能下降。

    不,不会的。由于这些是字符串文字,它们将在编译时进行评估,并且只会创建一个字符串。这是在Java Language Specification #3.10.5 中定义的:

    一个长字符串总是可以被分解成更短的部分,并使用字符串连接运算符 +
    写成一个(可能带括号的)表达式 [...]
    此外,字符串字面量总是引用 String 类的同一个实例。

    • 由常量表达式(第 15.28 节)计算的字符串在编译时计算,然后将其视为文字。
    • 在运行时通过连接计算的字符串是新创建的,因此是不同的。

    测试:

    public static void main(String[] args) throws Exception {
        String longString = "This string is very long.";
        String other = "This string" + " is " + "very long.";
    
        System.out.println(longString == other); //prints true
    }
    

    但是,下面的情况情况不同,因为它使用了一个变量——现在有一个连接,并且创建了几个字符串:

    public static void main(String[] args) throws Exception {
        String longString = "This string is very long.";
        String is = " is ";
        String other = "This string" + is + "very long.";
    
        System.out.println(longString == other); //prints false
    }
    

    【讨论】:

    • 我想他是在问它是否会为This stringThis string is 创建一个字符串。
    • @CodeBlue 是的,当且仅当您连接字符串文字时,您只会创建一个字符串。
    • @CodeBlue 仅池化字符串文字。在运行时创建的字符串不是。除非您使用intern() 方法强制他们进入池中。比如第二个代码sn -p,可以尝试使用String other = ("This string" + is + "very long.").intern();来看看区别。
    • @akash746 我不确定我是否理解你的问题。最好将其作为一个单独的问题提出,并提供更多详细信息。
    • 值得注意的是,如果我们在第二个示例中将final 修饰符添加到is" is " 将被视为文字,因此在输出中产生true
    【解决方案2】:

    在 Java 中连接字符串是否总是会导致在内存中创建新字符串?

    不,它并不总是这样做。

    如果连接是编译时常量表达式,则由编译器执行,并将生成的字符串添加到已编译类常量池中。在运行时,表达式的值是对应于常量池条目的实习String

    这将发生在您问题的示例中。

    【讨论】:

      【解决方案3】:

      请根据您的输入检查以下 sn-p:

      String longString = "This string is very long. It does not fit the width of the screen. So you have to scroll horizontally to read the whole string. This is very inconvenient indeed.";
      
      String longStringOther = "This string is very long. " + 
              "It does not fit the width of the screen. " +
              "So you have to scroll horizontally " +
              "to read the whole string. " +
              "This is very inconvenient indeed.";
      
      System.out.println(" longString.equals(longStringOther) :"+ longString.equals(longStringOther));      
      System.out.println(" longString == longStringother : " + (longString == longStringOther ));
      

      输出:

      longString.equals(longStringOther) :true
      longString == longStringother : 是的

      第一种情况:两个字符串相等(内容相同)

      2nd Case :表示串联后只有一个字符串。 所以只创建了一个字符串。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-06
        • 1970-01-01
        • 2019-07-03
        • 1970-01-01
        • 1970-01-01
        • 2020-01-09
        • 2011-09-20
        • 2018-04-27
        相关资源
        最近更新 更多