用Java连接字符串

时间:2012-07-21 16:08:51

标签: java string operator-overloading string-concatenation

  

可能重复:
  Why does + work with Strings in Java?

以下陈述在Java中有效。

int a=50;
String tmp="a = ";
String b=tmp+a;
String类型的

b现在包含a = 50(作为字符串)。

虽然tmp的类型为String,a的类型为int,但会进行连接(即使Java不支持运算符重载)。

Java不支持运算符重载的原因之一(与其他语言一样。事实上,我对任何语言都没有深度知识)。

  

Java不支持运算符重载。运算符重载有时是源代码   C ++程序中存在歧义,而Java设计团队认为它会带来更多麻烦   效益。

More关于它。

此声明String b=tmp+a;的评估方式如何?内部必须有一些等效的运算符重载概念。


只有一个问题:我们能看到字面它是如何实现的,或者我们应该只相信“它只是语言的一个功能”?

我听说Java编译器使用StringBuilder/StringBuffer(使用append()方法)来实现这一点,但我不确定。

3 个答案:

答案 0 :(得分:5)

从技术上讲,这只是一个碰巧具有相同符号的不同运算符。它是“字符串连接运算符”;见section 15.18.1 of the Java Language Specification

关于实施,JLS有这样说:

  

实现可以选择执行转换和连接   在一步中避免创建然后丢弃中间体   String对象。增加重复字符串的性能   连接,Java编译器可以使用StringBuffer类或a   类似的技术,以减少中间String对象的数量   通过评估表达式创建的。

     

对于原始类型,实现也可以优化掉   通过直接从基元转换来创建包装器对象   键入字符串。

答案 1 :(得分:2)

Java不允许用户定义的运算符重载。语言规范可以定义它想要的任何运算符:)

是的,您可以看到它是如何在内部完成的 - 使用javap -c来反汇编类。例如,在我的机器上,您的代码编译为:

   0: bipush        50
   2: istore_1
   3: ldc           #2    // String a =
   5: astore_2
   6: new           #3    // class java/lang/StringBuilder
   9: dup
  10: invokespecial #4    // Method java/lang/StringBuilder."<init>":()V
  13: aload_2
  14: invokevirtual #5    // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  17: iload_1
  18: invokevirtual #6    // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  21: invokevirtual #7    // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  24: astore_3
  25: return

但有些细节是特定于实现的;特别是,Sun / Oracle编译器使用来使用StringBuffer,但现在使用StringBuilder

答案 2 :(得分:-1)

编辑:即使编译器执行此更改(我不知道),使用String连接也是SLOWER然后使用StringBuilder。(错误=&gt; 不,编译器没有使用StringBuilder / StringBuffer )。您可以测试它只是创建一个简单的基准。 +运算符在Java中为字符串“重载”,但该语言不支持运算符重载。

尝试这样的方法来测试StringBuilder / StringBuffer:

String str = "";
StringBuffer sbf = new StringBuffer();
StringBuilder sb = new StringBuilder();

int nTests = 100;
int nConcats = 1000;

long initialTime = 0L;
long afterStrTime = 0L;
long afterSbfTime = 0L;
long afterSbTime = 0L;

for ( int i = 0; i < nTests; i++ ) {

    initialTime = System.currentTimeMillis();
    str = "";
    sbf = new StringBuffer();
    sb = new StringBuilder();

    for ( int j = 0; j < nConcats; j++ ) {
        str += "foo"; // or str = str + "foo"
    }
    afterStrTime = System.currentTimeMillis();

    for ( int j = 0; j < nConcats; j++ ) {
        sbf.append( "foo" );
    }
    afterSbfTime = System.currentTimeMillis();

    for ( int j = 0; j < nConcats; j++ ) {
        sb.append( "foo" );
    }
    afterSbTime = System.currentTimeMillis();

}

System.out.printf( "%d milliseconds to perform %d concatenations on String\n", afterStrTime - initialTime, nConcats );
System.out.printf( "%d milliseconds to perform %d concatenations on StringBuilder\n", afterSbfTime - afterStrTime, nConcats );
System.out.printf( "%d milliseconds to perform %d concatenations on StringBuffer\n",  afterSbTime - afterSbfTime, nConcats );

你会发现StringBuilder可以比StringBuffer更快,因为它不是同步的(StringBuffer是),并且两者都比String快。