假设字符串a和b:

a += b
a = a.concat(b)

在引擎盖下,它们是一样的吗?

这里是concat反编译作为参考。我希望能够反编译+操作符以及看看它做什么。

public String concat(String s) {

    int i = s.length();
    if (i == 0) {
        return this;
    }
    else {
        char ac[] = new char[count + i];
        getChars(0, count, ac, 0);
        s.getChars(0, i, ac, count);
        return new String(0, count + i, ac);
    }
}

当前回答

做一些简单的测试怎么样?使用下面的代码:

long start = System.currentTimeMillis();

String a = "a";

String b = "b";

for (int i = 0; i < 10000000; i++) { //ten million times
     String c = a.concat(b);
}

long end = System.currentTimeMillis();

System.out.println(end - start);

“a + b”版本在2500ms内执行。 a.concat(b)在1200ms内执行。

测试了几次。concat()版本的执行平均花费了一半的时间。

这个结果让我很惊讶,因为concat()方法总是创建一个新字符串(它返回一个“new string (result)”)。众所周知:

String a = new String("a") // more than 20 times slower than String a = "a"

为什么编译器不能在“a + b”代码中优化字符串创建,知道它总是导致相同的字符串?它可以避免创建新的字符串。 如果你不相信上面的说法,自己测试一下。

其他回答

为了完整起见,我想补充一下,'+'操作符的定义可以在JLS SE8 15.18.1中找到:

如果只有一个操作数表达式为String类型,则String 在另一个操作数上执行转换(§5.1.11)以生成一个 字符串。 字符串连接的结果是对string对象的引用 这是两个操作数字符串的连接。的字符 在右操作数字符的前面 新创建的字符串中的操作数。 String对象是新创建的(§12.5),除非表达式是 常量表达式(§15.28)

关于实现,JLS说了以下几点:

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression. For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string.

因此,从“Java编译器可能使用StringBuffer类或类似的技术来减少”判断,不同的编译器可以产生不同的字节码。

Tom准确地描述了+运算符的作用。它创建了一个临时的StringBuilder,添加了部分,并以toString()结束。

然而,到目前为止,所有的答案都忽略了HotSpot运行时优化的影响。具体来说,这些临时操作被认为是一种公共模式,并在运行时被更有效的机器代码所取代。

@marcio:你创建了一个微基准测试;在现代JVM中,这不是一种分析代码的有效方法。

运行时优化之所以重要,是因为一旦HotSpot开始运行,代码中的许多差异(甚至包括对象创建)就完全不同了。唯一确定的方法是在原位分析您的代码。

最后,所有这些方法实际上都非常快。这可能是一个过早优化的例子。如果您的代码连接了很多字符串,那么获得最大速度的方法可能与您选择的操作符无关,而是与您使用的算法有关!

当使用+时,速度会随着字符串长度的增加而降低,但是当使用concat时,速度会更稳定,最好的选择是使用StringBuilder类,它具有稳定的速度。

我想你能理解为什么。但是创建长字符串的最好方法是使用StringBuilder()和append(),这两种速度都是不可接受的。

基本上,+和concat方法之间有两个重要的区别。

If you are using the concat method then you would only be able to concatenate strings while in case of the + operator, you can also concatenate the string with any data type. For Example: String s = 10 + "Hello"; In this case, the output should be 10Hello. String s = "I"; String s1 = s.concat("am").concat("good").concat("boy"); System.out.println(s1); In the above case you have to provide two strings mandatory. The second and main difference between + and concat is that: Case 1: Suppose I concat the same strings with concat operator in this way String s="I"; String s1=s.concat("am").concat("good").concat("boy"); System.out.println(s1); In this case total number of objects created in the pool are 7 like this: I am good boy Iam Iamgood Iamgoodboy Case 2: Now I am going to concatinate the same strings via + operator String s="I"+"am"+"good"+"boy"; System.out.println(s); In the above case total number of objects created are only 5. Actually when we concatinate the strings via + operator then it maintains a StringBuffer class to perform the same task as follows:- StringBuffer sb = new StringBuffer("I"); sb.append("am"); sb.append("good"); sb.append("boy"); System.out.println(sb); In this way it will create only five objects.

伙计们,这就是+和concat方法的基本区别。 享受:)

我运行了类似于@marcio的测试,但使用了以下循环:

String c = a;
for (long i = 0; i < 100000L; i++) {
    c = c.concat(b); // make sure javac cannot skip the loop
    // using c += b for the alternative
}

为了更好的度量,我还添加了StringBuilder.append()。每个测试运行10次,每次运行100,000次。以下是调查结果:

StringBuilder轻松获胜。大多数运行的时钟时间结果为0,最长的运行时间为16毫秒。 A += b每次运行大约需要40000ms (40s)。 Concat每次运行只需要10000ms (10s)。

我还没有反编译类来查看内部结构或通过分析器运行它,但我怀疑a += b花了很多时间来创建StringBuilder的新对象,然后将它们转换回String。