Java 会在创建时更新字符串吗

hac*_*ddy 0 java string jvm string-concatenation

由于字符串在 Java 中是不可变的,这会创建 3 个对象,还是在内部仅创建一个对象。

在 JVM 中执行将如何发生,它是否取决于 JVM 实现?

class Main{
    public static void main(String[] args) throws Exception{
        
        String s = "FirstString" + "SecondString" + "ThirdString";

    }
}
Run Code Online (Sandbox Code Playgroud)

如果上面的情况在编译时解决了下面的情况如何工作。

class Main{
    public static void main(String[] args) throws Exception{
        
        String s = "FirstString" + "SecondString" + args[0];

    }
}
Run Code Online (Sandbox Code Playgroud)

Joa*_*uer 5

在这个例子中

String s = "FirstString" + "SecondString" + "ThirdString";
Run Code Online (Sandbox Code Playgroud)

连接+起来的 3 个常量字符串组成一个常量表达式。这意味着编译器可以在编译时知道该表达式的确切结果,因此将结果内联(即,结果.class文件看起来好像只有一个包含内容的常量FirstStringSecondStringThirdString)。

请注意,关于什么算作常量表达式的确切规则不是很直观,因此如果有兴趣,请查看 JLS 以获取详细信息。

String s = "FirstString" + "SecondString" + someStringVariable;
Run Code Online (Sandbox Code Playgroud)

第一个连接将被简单地“折叠” "FirstStringSecondString",第三个连接将在运行时以“正常”方式完成。

Java 9 中在运行时进行字符串连接具体方式非常复杂,并且会导致池中的相关常量条目成为"FirstStringSecondString\u0001"(注意尾随\u0001指示参数的去向)。但它仍然表明该表达式中的第一个连接是在编译期间从.javato解析的.class

这让我们意识到,即使

    String s = "First" + "Second" + someStringVariable + "Last";
Run Code Online (Sandbox Code Playgroud)

将被优化为单个操作,因为在这种情况下使用的常量是"FirstSecond\u0001Last"