Although the world is full of suffering, it is full also of the overcoming of it!
虽然世界充满了苦难,但总是能战胜的。——海伦-凯勒
五十二、推荐使用String直接赋值
一般对象都是通过new关键字生成的,但是String还有第二种生成方式,也就是我们经常使用的直接声明方式,即通过直接量进行赋值。
Java中设计了一个字符串常量池,在字符串常量池中所容纳的都是String字符串对象。它的创建机制是这样的:创建字符串时,首先检查常量池中是否有字面值相等的字符串,如果有,则不再创建,直接返回常量池中该对象的引用,若没有则创建之,然后放到常量池中,并返回新建对象的引用。
利用对象池,不仅可以提高效率,同时也减少了内存空间的占用,建议大家在开发中使用直接量赋值方式,除非确有必要才新建立一个String对象。
五十三、注意方法中传递的参数要求
replaceAll方法要求第一个参数是一个正则表达式,符合正则表达式的字符串才会被替换。可以用replace代替replaceAll。
五十四、正确使用String、StringBuffer、StringBuilder
String类是不可改变的量,也就是创建之后就不能再修改了。
StringBuffer是一个可变字符序列,它与String一样,在内存中保存的都是一个有序的字符序列(char类型的数组),不同点是StringBuffer的值是可以改变的。
StringBuilder与StringBuffer基本相同,都是可变字符序列,不同点是:StringBuffer是线程安全的,StringBuilder是线程不安全的。翻翻两者的源码,就会发现,StringBuffer的方法前都有synchronized关键字,这也是StringBuffer性能远低于StringBuilder的原因。
弄清楚了三者的原理,我们就可以在不同的场景下使用不同的字符序列了:
- 使用String类的场景。在字符串不经常变化的场景中,可以使用String类。
- 使用StringBuffer的场景。在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用StringBuffer,例如XML解析、HTTP参数解析和封装等。
- 使用StringBuilder类的场景。在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程环境中,则可以考虑使用StringBuilder, 例如SQL语句的拼装,JSON封装等。
五十五、注意字符串的位置
在“+”表达式中,String字符串具有最高优先级。
五十六、自由选择字符串拼接方法
对一个字符串拼接有三种方法:加号,concat方法,StringBuffer和StringBuilder的append方法。其中加号是最常用的,三者有什么区别?append方法拼接速度最快,concat次之,加号最慢。这是为何?
- 加号方法拼接字符串。加号拼接代码如同下面代码:
str = new StringBuilder(str).append("c").toString();
它与StringBuilder不同的是,每次都会创建一个StringBuilder对象,每次都要调用toString方法,它的执行时间都消耗在这里了。
- concat方法拼接字符串,源码如下:
public String concat(String str){
int otherLen = str.length();
if(otherLen == 0){
return this;
}
char[] buf = new char[count + otherLen];
getChars(0, count, buf, 0);
str.getChars(0, otherLen, buf, count);
return new String(0, count + otherLen, buf);
}
最后的return语句中每次创建一个String对象是concat速度慢下来的真正原因。
3.append方法拼接。StringBuilder的append方法直接父类AbstractStringBuilder实现,代码如下:
public AbstractStringBuilder append(String str){
if(str == null) {
str = "null";
}
int len = str.length();
if(len == 0){
return this;
}
int newCount = count + len;
if(newCount > value.length){
expandCapacity(newCount);
}
str.getChars(0, len, value, count);
count = newCount;
return this;
}
处理过程中没有新建任何对象,所以速度快多了。
五十七、推荐在复杂字符串操作中使用正则表达式
使用正则表达式判断输入的字符串str中有多少个中英文单词:
Pattern pattern = Pattern.compile("\\b\\w+\\b");
Matcher matcher = pattern.matcher(str);
五十八、强烈建议用UTF编码
在项目中统一编码很重要,防止乱码的产生。
五十九、对字符串排序持一种宽容的心态
Java推荐用Collator类进行排序。