《编写高质量Java》(六)

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的原因。
弄清楚了三者的原理,我们就可以在不同的场景下使用不同的字符序列了:

  1. 使用String类的场景。在字符串不经常变化的场景中,可以使用String类。
  2. 使用StringBuffer的场景。在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用StringBuffer,例如XML解析、HTTP参数解析和封装等。
  3. 使用StringBuilder类的场景。在频繁进行字符串的运算(如拼接、替换、删除等),并且运行在单线程环境中,则可以考虑使用StringBuilder, 例如SQL语句的拼装,JSON封装等。

五十五、注意字符串的位置

在“+”表达式中,String字符串具有最高优先级。

五十六、自由选择字符串拼接方法

对一个字符串拼接有三种方法:加号,concat方法,StringBuffer和StringBuilder的append方法。其中加号是最常用的,三者有什么区别?append方法拼接速度最快,concat次之,加号最慢。这是为何?

  1. 加号方法拼接字符串。加号拼接代码如同下面代码:
str = new StringBuilder(str).append("c").toString();

它与StringBuilder不同的是,每次都会创建一个StringBuilder对象,每次都要调用toString方法,它的执行时间都消耗在这里了。

  1. 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类进行排序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容