java中String的+运算符

六只 发布于 2012/02/06 15:29
阅读 5K+
收藏 2

java是不支持运算符重载的,String的+会被转化为StringBuilder的append方法实现,那么怎么才能看到java是如何解析这个+运算符的实现呢?

求指点。

加载中
1
Jeky
Jeky

你可以使用javap -verbose 来查看已经编译好的class文件

写一个简单的字符串相加:

public class Test{

	public static void main(String[] args){
		String s1 = "a";
		String s2 = "b";
		String s = s1 + s2;
	}
}

编译以后查看字节码:

public static void main(java.lang.String[]);
  Code:
   Stack=2, Locals=4, Args_size=1
   0:   ldc     #2; //String a
   2:   astore_1
   3:   ldc     #3; //String b
   5:   astore_2
   6:   new     #4; //class java/lang/StringBuilder
   9:   dup
   10:  invokespecial   #5; //Method java/lang/StringBuilder."<init>":()V
   13:  aload_1
   14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
   17:  aload_2
   18:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/la
ng/String;
   24:  astore_3
   25:  return

 从第6行到第21行 可以看出 a + b被编译为:

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

a
aine_pan
如果这样的话,string+string+string+string 的性能也不会差太多啊,因为底层实现是用stringbuild来实现的,跟直接用stringbuild是差不多的! 为什么很多人会说string+string会增加额外的系统开销呢?
Jeky
Jeky
@六只 : 这个我还真不清楚 不过我猜应该能找到官方资料才对
六只
六只
嗯,有手段查看:如何分析这个+号是String的拼接运算吗?
李克华
李克华
牛人!
0
放牛娃1988
放牛娃1988
Java只是不支持自定义运算符重载,这个String类的+就是运算符重载,也是Java中仅有的一个运算符重载,它是通过编译器实现的,在语法解析阶段就已经确定了。
放牛娃1988
放牛娃1988
可以查看字节码,不过我没看过,呵呵:)
六只
六只
哦,想是可以想到。我是想找到“有力”的证据。哈哈。
放牛娃1988
放牛娃1988
@六只 : 这个可以自己想吧,比如 a + b + c就是(new StringBuilder()).append(a).append(b).append(c).toString()
六只
六只
那有办法看到语法分析的实现吗?
0
被风遗忘
被风遗忘

String中的"+"应该是连接符意思吧.

更好实现可以用StringBuilder().append(a).append(b).toString();这样写可以组成一个对象.如果是用"+"的话,每一个"+"就会去创建一个对象,在系统内存中.

0
hillshills
hillshills
Jeky 的说法,学习了。
0
Jeky
Jeky

回复 @aine_pan : 是这样的,很早很早的时候,Java编译的时候还不会这么优化,于是大量的书籍就会普及使用StringBuffer来连接字符串。后来Java编译时开始优化这个内容,但是那些书籍依然被广泛阅读(尤其广泛地分布在中国的大学里),所以就导致了这个说法一直保留至今。

另外,如果在循环中连接字符串,还是依然建议显式使用StringBuilder。因为编译器优化时,会在每次循环的开始时建立一个新的StringBuilder变量,如果循环次数很多,这种建立消耗资源也不小。

0
a
aine_pan

引用来自“Jeky”的答案

回复 @aine_pan : 是这样的,很早很早的时候,Java编译的时候还不会这么优化,于是大量的书籍就会普及使用StringBuffer来连接字符串。后来Java编译时开始优化这个内容,但是那些书籍依然被广泛阅读(尤其广泛地分布在中国的大学里),所以就导致了这个说法一直保留至今。

另外,如果在循环中连接字符串,还是依然建议显式使用StringBuilder。因为编译器优化时,会在每次循环的开始时建立一个新的StringBuilder变量,如果循环次数很多,这种建立消耗资源也不小。

好吧!我做了个实验:

public static void testString(){
String a = new String("a");
StringBuilder b = new StringBuilder("b");
StringBuffer c = new StringBuffer("c");
long star = System.currentTimeMillis();
for(int i=0;i<100000;i++){
a+="a";
}
long end = System.currentTimeMillis();
print("String:"+(end-star));

star = System.currentTimeMillis();
for(int i=0;i<100000;i++){
b.append("b");
}
end = System.currentTimeMillis();
print("StringBuilder:"+(end-star));

star = System.currentTimeMillis();
for(int i=0;i<100000;i++){
c.append("c");
}
end = System.currentTimeMillis();
print("StringBuffer:"+(end-star));
}
结果是:

String:5284
StringBuilder:6
StringBuffer:9

说明性能还是差距蛮大的,在多循环里面。

Builder比buffer少了个同步方法,效率也是有点提升的。


返回顶部
顶部