假设字符串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);
    }
}

当前回答

基本上,+和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方法的基本区别。 享受:)

其他回答

这里的大多数答案都来自2008年。随着时间的推移,情况似乎发生了变化。我最近用JMH做的基准测试显示,在Java 8 +上比concat快两倍左右。

我的基准:

@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
public class StringConcatenation {

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State2 {
        public String a = "abc";
        public String b = "xyz";
    }

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State3 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
    }


    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State4 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
        public String d = "!@#";
    }

    @Benchmark
    public void plus_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b);
    }

    @Benchmark
    public void plus_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c);
    }

    @Benchmark
    public void plus_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c+state.d);
    }

    @Benchmark
    public void stringbuilder_2(State2 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).toString());
    }

    @Benchmark
    public void stringbuilder_3(State3 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).toString());
    }

    @Benchmark
    public void stringbuilder_4(State4 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).append(state.d).toString());
    }

    @Benchmark
    public void concat_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b));
    }

    @Benchmark
    public void concat_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c)));
    }


    @Benchmark
    public void concat_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c.concat(state.d))));
    }
}

结果:

Benchmark                             Mode  Cnt         Score         Error  Units
StringConcatenation.concat_2         thrpt   50  24908871.258 ± 1011269.986  ops/s
StringConcatenation.concat_3         thrpt   50  14228193.918 ±  466892.616  ops/s
StringConcatenation.concat_4         thrpt   50   9845069.776 ±  350532.591  ops/s
StringConcatenation.plus_2           thrpt   50  38999662.292 ± 8107397.316  ops/s
StringConcatenation.plus_3           thrpt   50  34985722.222 ± 5442660.250  ops/s
StringConcatenation.plus_4           thrpt   50  31910376.337 ± 2861001.162  ops/s
StringConcatenation.stringbuilder_2  thrpt   50  40472888.230 ± 9011210.632  ops/s
StringConcatenation.stringbuilder_3  thrpt   50  33902151.616 ± 5449026.680  ops/s
StringConcatenation.stringbuilder_4  thrpt   50  29220479.267 ± 3435315.681  ops/s

+运算符可以在字符串、char、integer、double或float数据类型值之间工作。它只是在连接之前将值转换为字符串表示形式。

concat操作符只能在字符串上执行。它检查数据类型兼容性,如果不匹配,则抛出错误。

除此之外,您提供的代码也做同样的事情。

我不这么想。

a.concat(b)是在String中实现的,我认为自早期java机器以来,实现没有太大变化。+操作的实现取决于Java版本和编译器。目前+是使用StringBuffer实现的,以使操作尽可能快。也许在未来,这种情况会改变。在java +的早期版本中,对字符串的操作要慢得多,因为它产生中间结果。

我猜+=是使用+实现的,并进行了类似的优化。

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

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

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

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

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

Niyaz是正确的,但同样值得注意的是,特殊的+运算符可以被Java编译器转换为更有效的东西。Java有一个StringBuilder类,它表示一个非线程安全的可变String。当执行一系列String连接时,Java编译器会静默地进行转换

String a = b + c + d;

into

String a = new StringBuilder(b).append(c).append(d).toString();

这对于大字符串来说效率更高。据我所知,使用concat方法时不会发生这种情况。

然而,concat方法在将空字符串连接到现有字符串时效率更高。在这种情况下,JVM不需要创建新的String对象,只需返回现有的String对象。请参阅concat文档来确认这一点。

所以如果你非常关心效率,那么你应该在连接可能为空的字符串时使用concat方法,否则使用+。然而,性能差异应该可以忽略不计,您可能永远都不应该担心这一点。