java中操作字符串都有哪些类,他们之间有什么区别?

java中操作字符串的类有哪些?

  • String
  • StringBuffer
  • StringBuilder

区别

  • 我们可以先看一下这几个类的继承关系图
    java中操作字符串都有哪些类,他们之间有什么区别?_第1张图片java中操作字符串都有哪些类,他们之间有什么区别?_第2张图片
    java中操作字符串都有哪些类,他们之间有什么区别?_第3张图片
    从类的继承关系上来开的话,String和StringBuffer,StringBuilder是没有任何关系的,但是StringBuffer和StringBuilder的继承关系时一样的.
  • 然后我们在通过断点看一下他们几个类创建出来的对象都是什么样的
    java中操作字符串都有哪些类,他们之间有什么区别?_第4张图片 java中操作字符串都有哪些类,他们之间有什么区别?_第5张图片
    java中操作字符串都有哪些类,他们之间有什么区别?_第6张图片
    从这里我们可以看出来,这三个类存储的本质都是一个char类型数组.不同的是String类型的数组长度是3,而另外两个数组的长度都是19且默认值为0.
  • 我们还可以看一下三个类的方法,其中String类是不可变的字符串,而另外两个类都是可以对字符串进行追加的.看一下追加扩容的方法
    java中操作字符串都有哪些类,他们之间有什么区别?_第7张图片
    java中操作字符串都有哪些类,他们之间有什么区别?_第8张图片
    追加的方法实际上都是调用父类的追加方法,但是StringBuffer类中多了一行toStringCache = null;的代码,其中toStringCache是一个char[];这个属性在重写toString()方法中使用了,具体可以自行看源码.我们在看下父类的追加方法:
    java中操作字符串都有哪些类,他们之间有什么区别?_第9张图片
    这个才是最终的执行添加的方法,我们重点看下红框中的代码,count是现在对象中的字符串的长度,len是要追加的字符串的长度,这两个相加之后就是追加完之后的字符串的长度,传到了 ensureCapacityInternal(int minimumCapacity)方法中,我们在点进去看下这个方法:
    java中操作字符串都有哪些类,他们之间有什么区别?_第10张图片
    之前我们说了,StringBuffer和StringBuilder都是用char[]进行存储,并且初始化的时候数组的长度是19,当前的value.length实际就是代表当前char[]的长度,这里用传进来的字符串追加厚的实际长度与char数组的长度进行减法操作,也就是判断当前char[]数组能不能装下这个追加之后的字符串,能装下的话什么都不做,不能装下的话会使用Arrays.copyOf()方法将现有的char[]数组赋值到新的char数组中,新数组的长度使用newCapacity()方法获得,我们看下自动扩容的长度是:
    java中操作字符串都有哪些类,他们之间有什么区别?_第11张图片

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 传入的是追加之后的字符串的长度,先将当前char[]的长度*2((value.length << 1))在加上2的值做为新的char[]的长度
     * 然后判断新的char的长度是否能够存储追加之后的字符串,如果长度还不够,就将追加之后的字符串的长度直接赋值给新char的长度.
     * 在判断新的char的长度的值是否合法,也就是在0-Integer.MAX_VALUE - 8之间并且不包括0就直接返回新的字符串长度,否则进行进一步处理.
     **/
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        int newCapacity = (value.length << 1) + 2;
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
                ? hugeCapacity(minCapacity)
                : newCapacity;
    }

    private int hugeCapacity(int minCapacity) {
        if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
                ? minCapacity : MAX_ARRAY_SIZE;
    }
    

到这里我们能够看出,进行扩容处理还是比较复杂的,所以如果可以的话,我们还是指定长度,避免自动扩容

  • 在看一下之前的StringBuffer和StringBuilder的append()方法
    java中操作字符串都有哪些类,他们之间有什么区别?_第12张图片
    java中操作字符串都有哪些类,他们之间有什么区别?_第13张图片
    在StringBuffer类中的方法绝大部分都加了synchronized关键字,而StringBuilder类中则没有,所以说StringBuffer类是线程安全的,而StringBuilder则不是线程安全的.

这个问题到底怎么回答?

关于这个问题,网上真的有好多,不说写烂了也差不多吧,但是具体怎么回答,我相信如果你真的理解这些也就好回答了,本文主要想表达是类似问题到底应该怎么去找答案,看源码是个很好的方式.

我认为所有的有什么区别的问题,都可以这样回答

  1. A这个类是干什么的
  2. B这个类是干什么的
  3. 这两个类你都说完了之后,然后说A和B那里不一样,应该就可以了吧,
  4. 在好点的话说说什么情境下使用A,什么情景下使用B,理由是什么.应该就ok了

我的答案

java中操作字符串的类,我知道的有三个类,分别是String,StringBuffer和StringBuilder.这三个类都是以char[]的形式保存的字符串,但是String类型的字符串是不可变的,对String类型的字符床做修改操作都是相当于重新创建对象.而对StringBuffer和StringBuilder进行增删操作都是对同一个对象做操作.StringBuffer中的方法大部分都使用synchronized关键字修饰,所以StringBuffer是线程安全的,StringBuilder中的方法则没有,线程不安全,但是StringBuilder因为没有使用使用synchronized关键字修饰,所以性能更高,在单线程环境下我会选择使用StringBuilder,多线程环境下使用StringBuffer.如果生命的这个字符串几乎不做修改操作,那么我就直接使用String,因为不调用new关键字声明String类型的变量的话它不会在堆内存中创建对象,直接指向String的常量池,并且可以复用.效率更高.到这时候还不过瘾的话你就接着说这三个类创建的时候都是什么状态,扩容的时候又怎么扩容的等等,感觉应聘的初级程序员应该够用了吧…在不行就给他讲内存原理给它画图,还不行,那我也没办法了,估计你应聘的应该是架构…坦白说自己就知道这么多.

你可能感兴趣的:(面试)