给3个建议:
1.没有在循环体中修改字符串的情况,不要轻易用StringBuilder,如果理解不深,容易适得其反;
2.在代码中写sql有时候很长,直接用“+”号拼接;
3.代码中sql的参数用问号代替,用预编译的形式,产生的垃圾对象是最少的。
如果要问为什么,请看下面;
1问下面代码产生了再会产生几个对象
private static String test1() {
String str = "hello " + "word" + "!!";
return str;
}
答:在不考虑前后代码关系的情况下,这里只会产生1个对象!具体分析很简单,通过class文件反编译就能看到结果“”
private static String test1() {
String str = "hello word!!";
return str;
}
反编译之后,那些“+”号已经被java编译器处理了,这段代码运行过程大概是这样的:1.产生一个匿名字符串对象"hello word!!"直接入池;2.str指向常量池"hello word!!"地址。
2问不考虑前后影响,下面代码会产生几个对象,str指向的是不是常量池;
private static String test2() {
String str1 = "word";
String str = "hello "+ str1 + "!!";
return str;
}
答:产生了4个对象。str指向的不是常量池。看反编译结果:
private static String test2() {
String str1 = "word";
String str = "hello " + str1 + "!!";
return str;
}
四个对象分别是池中的 “word”、"hello "、 "!!“和非池中的"hello word!!”;为啥"hello word!!"没有入池,因为String str = "hello " + str1 + “!!”;等效于 String str = new StringBuilder().append( "hello ").append( str1).append( “!!”) .toString()。这里面产生了两个字符串的匿名对象,和一个StringBuilder对象,感觉还好。
3问下面代码会产生几个对象
private static String test3() {
String str = "-1";
for(int i =0;i<10;i++ ) {
str += i;
}
return str;
}
答:这个才是使用StringBuider或者buffer的场景。11个对象,最终没有入池。因为这段代码编译后将等效于下面这段代码,没进入一次循环体都会创建一个对象,
private static String test() {
String str = "-1";
for(int i =0;i<10;i++ ) {
str =new StringBuffer().append(str).append(i).toString();
}
return str;
}
不是每个场景都要用StringBuilder的,要具体情况具体分析。除了循环修改字符串的情况,其他情况尽量不要手撸StringBuilder。有必要的时候java会帮忙优化的,这样还能保持较高的可读性。对于较长的sql拼接,有时候还会涉及StringBuilder扩容问题,让程序性能更差(当然明白这一点之后还是可以手动优化的);
如果一定要用,那可以先看看StringBuilder的构造方法,对于确定长度的字符串拼接,其中还有变量的,可以自己定义长度,避免扩容给效率带来影响。
上面的结论90%我都通过自己的方法验证过,部分结论是通过别人的资料的出来的。有兴趣提供验证方法的请留下评论。