java中字符串相加本质到底是怎样的?

wts 2004-12-15 01:59:53
String s = "a" + "b" + "c";
这里,我们先不考虑"a","b","c"是放置在池中这个问题。
这个"+"操作符,java到底是怎么对待的?
一种说法是"a"是一个字符串对象,+"b"之后,又生成一个字符串对象,大概是"ab",+"c"之后,再生成一个字符串对象,大概是"abc",
然后,把"abc"字符串对象的引用返回给s。这样,在这个过程中,共有6个字符串对象产生,这样效率低,所以应该用StringBuffer实现,
如:
StringBuffer sb = new StringBuffer(100);
sb = sb.append("a").append("b").append("c");
再有一个说法,是java对“+”操作符进行重载,最终以StringBuffer实现以上字符串相加动作。
到底哪个说法对?其实以上的问题,也就是问,java对“+”到底重载成什么样子?
...全文
2392 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
MYLiao 2005-01-28
  • 打赏
  • 举报
回复
String s = "a" + "b" + "c";
这里只有一个内存地址 S;

String a = "a";
String b = "b";
String c = "c";
String s = a + b + c;
这里有四个内存地址,显然效率就不一样。
likeblood 2005-01-27
  • 打赏
  • 举报
回复
建议去看下原代码
不是很难理解
MAXIMO51 2005-01-26
  • 打赏
  • 举报
回复
不错,值得学习。
nwsl 2005-01-26
  • 打赏
  • 举报
回复
生成新的对象。
wts 2004-12-25
  • 打赏
  • 举报
回复
题外话,也是经验吧?同样欢迎。谢谢
lxy80920 2004-12-25
  • 打赏
  • 举报
回复
说得透彻
allenhe 2004-12-23
  • 打赏
  • 举报
回复
插题外话
String s = "a" + "b" + "c";

实际上编译出来是String s = "abc";不存在相加问题

实际上这种情况才会生成StringBuffer
String a = "a";
String b = "b";
String c = a+b;//<-生成了StringBuffer

所以第一种问题不大,个人爱好问题,比如拼sql,有时候这样写看起来比较舒服
第二种是尽量不用的

呵呵,题外话
wts 2004-12-23
  • 打赏
  • 举报
回复
还有其它人要补充的吗?
zcjl 2004-12-22
  • 打赏
  • 举报
回复
至少在我目前的使用经验上可以得出这个结论
有什么疏漏的,还请指出
wts 2004-12-22
  • 打赏
  • 举报
回复
那是不是说结论:
除非是在循环中,进行类似字符串相加操作,否则不需要考虑是用String,还是用StringBuffer?
sep11 2004-12-22
  • 打赏
  • 举报
回复
很厉害,顶一下
stephen129 2004-12-22
  • 打赏
  • 举报
回复
up
programeyonger 2004-12-22
  • 打赏
  • 举报
回复
说的很好!顶!!
yielruse 2004-12-22
  • 打赏
  • 举报
回复
从底层着手来讲解这个问题
这个方法实在是高啊
值得学习.
jxjrsuibian 2004-12-22
  • 打赏
  • 举报
回复
讲的很透彻,顶
tom2005 2004-12-22
  • 打赏
  • 举报
回复
好,ding
zcjl 2004-12-21
  • 打赏
  • 举报
回复
String s = "a" + "b" + "c";
就等于String s = "abc";

String a = "a";
String b = "b";
String c = "c";
String s = a + b + c;
这个就不一样了,好像最终结果类似于:
StringBuffer temp = new StringBuffer();
temp.append(a).append(b).append(c);
String s = temp.toString();
bonniewater 2004-12-21
  • 打赏
  • 举报
回复
zcjl 2004-12-21
  • 打赏
  • 举报
回复
至于推荐用StringBuffer来代替String+拼装字符串,说的是循环方式下,如:

public class Test4 {
public static void main(String[] args) {
String s = "s";
for (int i = 0; i < 20; i++) {
s += i;
}
}
}

对应的bytecode为:

public class Test4 extends java.lang.Object{
public Test4();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: ldc #2; //String s
2: astore_1
3: iconst_0
4: istore_2
5: iload_2
6: bipush 20
8: if_icmpge 36
11: new #3; //class StringBuffer
14: dup
15: invokespecial #4; //Method java/lang/StringBuffer."<init>":()V
18: aload_1
19: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
22: iload_2
23: invokevirtual #6; //Method java/lang/StringBuffer.append:(I)Ljava/lang
/StringBuffer;
26: invokevirtual #7; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
29: astore_1
30: iinc 2, 1
33: goto 5
36: return

}

如果用String+的方式,每循环一次,就会重新new一个StringBuffer对象,这样的内存消耗完全是不必要的(在数据量大的情况下,还会导致内存不足的错误),所以要这样做:

public class Test5 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("s");
for (int i = 0; i < 20; i++) {
sb.append(i);
}
}
}
这样无论循环多少次,都只会生成一个StringBuffer对象
zcjl 2004-12-21
  • 打赏
  • 举报
回复
用bytecode来说明问题:

1.使用String + 的方式:
public class Test2 {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "c";
String s = a + b + c;
}
}

对应的bytecode为:

public class Test2 extends java.lang.Object{
public Test2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: ldc #2; //String a
2: astore_1
3: ldc #3; //String b
5: astore_2
6: ldc #4; //String c
8: astore_3
9: new #5; //class StringBuffer
12: dup
13: invokespecial #6; //Method java/lang/StringBuffer."<init>":()V
16: aload_1
17: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
20: aload_2
21: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
24: aload_3
25: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
28: invokevirtual #8; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
31: astore 4
33: return

}

2.使用StringBuffer.append()的方式:
public class Test3 {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "c";
StringBuffer sb = new StringBuffer();
sb.append(a).append(b).append(c);
String s = sb.toString();
}
}

对应的bytecode为:

public class Test3 extends java.lang.Object{
public Test3();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: ldc #2; //String a
2: astore_1
3: ldc #3; //String b
5: astore_2
6: ldc #4; //String c
8: astore_3
9: new #5; //class StringBuffer
12: dup
13: invokespecial #6; //Method java/lang/StringBuffer."<init>":()V
16: astore 4
18: aload 4
20: aload_1
21: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
24: aload_2
25: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
28: aload_3
29: invokevirtual #7; //Method java/lang/StringBuffer.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuffer;
32: pop
33: aload 4
35: invokevirtual #8; //Method java/lang/StringBuffer.toString:()Ljava/lan
g/String;
38: astore 5
40: return

}

看到了么?后者不光不比前者效率高,反而多了一些临时变量的存取
加载更多回复(13)

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧