妙谈String,StringBuffer,StringBuilder

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    省略一万个字
}

从jdk源码中可以发现,String类使用字符数组保存字符串(char value[]),同时被final关键字修饰,所以String对象是不可变的。下面代码中两个字符串变量的名称不同,但从输出结果发现,他们竟然有相同的hashcode。这是因为String变量在内存中是共享的,变量a与b指向的是同一块内存。这里很奇怪,前面为什么说String对象是不可修改的,但是却可以通过‘+=’来改变a中的内容。其实jdk是通过重新开拓一片内存,存放计算之后的数据。再将这块区域的引用给a对象。通过运行结果可以看出,a在进行了计算之后,hashcode发生了改变,并非其值变化了,而是引用变化了。

public static void main(String[] args) {
        String a = "12";
        String b = "12";
        System.out.println(a.hashCode());
        System.out.println(b.hashCode());
        a+="1";
        System.out.println(a);
        System.out.println(a.hashCode());
    }

//输出结果如下
1569
1569
121
48688

Process finished with exit code 0

总结,String是常量并且在内存中是共享的,因为是常量,所以String的线程是安全的。(强制安全)。

而StringBuilder和StringBuffer都继承于AbstractStringBuilder类。

abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     * The value is used for character storage.
     */
    char[] value;
//此处省略一万个字
}

AbstractStringBuilder类也是通过字符数组存储字符串,但是却没有final修饰关键字,因此StringBuilder和StringBuffer是可变字符串,和普通对象无异。由于重写了其父类中的许多方法如toString,length,insert,append。因此StringBuilder和StringBuffer的操作比String更灵活,实际应用范围也更广。

 @Override
    public StringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

StringBuilder和StringBuffer最大的区别在于StringBuffer是线程安全的,StringBuilder的线程不安全。因为StringBuffer内部的方法加了synchronized修饰,成为了同步方法。若对数据安全性要求不高,从性能和轻量级的角度来看 建议使用StringBuilder。对于安全性要求很高的数据必须使用StringBuffer。

public synchronized StringBuffer append(StringBuffer sb) {
        toStringCache = null;
        super.append(sb);
        return this;
    }

    /**
     * @since 1.8
     */
    @Override
    synchronized StringBuffer append(AbstractStringBuilder asb) {
        toStringCache = null;
        super.append(asb);
        return this;
    }

明天将再从源码的角度,谈谈synchronized的底层原理,为什么会影响性能,以及锁升级的相关概念,请大家继续关注。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java上路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值