Java--String类(StringBuilder与StringBuffer)

String类的特征:

        String类的特点:

1. String 类在设计时就是不可改变的, String 类实现描述中已经说明了

        String部分源码如下:

2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象
        例如replace方法:

   public static void main(String[] args) {
        String s1 = "abcdef";
        String s2 = s1.replaceAll("a","b");
        System.out.println(s2);
    }

        我将所有的a换成b,此时究竟是在原来的字符串基础上改呢?还是new了一个新的String类?

源码如下:

        

里面确实new了一个新的String类!!!

注意:

final 修饰类表明该类不想被继承, final 修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的

例如: 

 public static void main(String[] args) {
        final int array[] = {1,2,3,4,5};
        int arr[] = {1,2,3};
        array[0] = 100;
        System.out.println(Arrays.toString(array));
// array = new int[]{4,5,6}; // 编译报错:Error:(19, 9) java: 无法为最终变量array分配值
为什么 String 要设计成不可变的 ? ( 不可变对象的好处是什么 ?) ( 选学 )
1. 方便实现字符串对象池 . 如果 String 可变 , 那么对象池就需要考虑写时拷贝的问题了 .
2. 不可变对象是线程安全的.
3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap

字符串修改:

        刚刚解释完,String中的字符串中的char[]数组引用被final修饰,不可再引用其他对象!!
所以要想修改字符串肯定是new一个新的String引用其他字符串!

    public static void main(String[] args) {
        String s = "hello";
        s += " world";//s = s+"world"
        System.out.println(s); // 输出:hello world
    }

 我们可以从反汇编代码的角度观察一下:

 我们也可以用另一套代码写出同样的效果:

    public static void main(String[] args) {
        String s = "hello";
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(s);
        stringBuilder.append("world");
        s = stringBuilder.toString();
        System.out.println(s);
    }

通过反汇编可以看到本质,相当于new了一个新的对象,也就是一共有三个对象参加这次运行。有人问了,哪有三个对象,我怎么看不到。

我们一起来分析一下:

s是不是一个对象!

world也是一个对象!

注意,这里的toString也会返回一个新的对象:
源代码如下:

所以说最后肯定是一个新的对象,只不过是s引用了这个新的对象!!

这时候应该提出疑问,这个StringBuilder这个类是干什么的??

接下来一探究竟:

StringBuilder类与StringBuffer类:

        由于String 的不可更改特性,为了方便字符串的修改, Java 中又提供 StringBuilder StringBuffer 类。这两个类大部分功能是相同的,这里介绍 StringBuilder 常用的一些方法,

StringBuilder:

StringBuilder方法也是不可被继承的,而且继承了父类AbstractStringBuilder类,同时还有两个接口!

构造函数:

StringBuilder构造函数有好多重载:

例如:

1、无参构造:
                

2、传整型构造:

3、传字符串构造:

那么每次构造如果调用了super(),这个究竟是干什么的,得从父类入手:

AbstractStringBuilder类:

        

我们发现父类中有两个成员变量:

有一个是字符数组,一个是整型。

而且如果是传带有参数的super会调用第二个构造函数,我们发现其实他是在new一个大小为capacity的字符数组!!

也就是它的底层是字符数组,在字符数组的基础上进行修改,也就不会多次new性的对象,提高性能!

append方法:

该方法就可以实现追加功能,也就是修改字符串,他是怎么实现的呢?

   public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

 当然append方法也有许多重载的方法,传入的参数有所差异。

就拿传一个字符串类型为例:
我们可以不用去管具体的实现细节,但是我们可以看出,在这个过程中没有再new一个新的对象,而且最后返回的还是自己。

这里就与String类型中的拼接字符串是有区别的了!!

我们可以用Stringbuilder类中的append方法完成拼接:

    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("abcd");
        stringBuilder.append("efg");
        System.out.println(stringBuilder);
    }

 注意:最后打印的时候直接传入stringbuild即可。

reverse反转字符串:

        这个方法也很厉害,在StringBuilder类的方法中有一个方法可以直接反转字符串!!

例如:

    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder("abcdef");
        stringBuilder =  stringBuilder.reverse();
        System.out.println(stringBuilder);
    }

注意:

reverse方法的返回值是stringbuilder类型!!

StringBuffer:

StringBuffer和StringBuilder是差不多的,包括一些方法,用法都是差不多的。

但是唯一的区别是什么:

 我们需要关注一下它的append方法:

我们发现类比StringBuilder多了一行代码:

这行代码是干什么的呢?

这行代码可以理解为是一把锁,当程序运行时会所起来,结束后才会解开:

主要运用在多线程中!

 String、StringBuilder、StringBuffer的区别:

String 的内容不可修改, StringBuffer StringBuilder 的内容可以修改 .
StringBuffer StringBuilder 大部分功能是相似的
StringBuffer 采用同步处理,属于线程安全操作;而 StringBuilder 未采用同步处理,属于线程不安全操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值