以下陈述在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()
方法)来实现这一点,但我不确定。
答案 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快。