Java基础——String、String Builder和String Buffer类

String

String实际上就是一个字符数组;
初始化方法:
1) char[] c = {‘a’,‘b’};
String s1 = new String©;
2)String s2 = new String{‘a’,‘b’};
3)String s3 = “ab”;

常用方法:

        String s= "abc";
        s.charAt(0);
        s.indexOf('b');
        s.substring(0);
        s.replace('b', 'c');
        s.split("a");
        s.toCharArray();
        s.lastIndexOf("a");
        s.endsWith("d");
        s.toUpperCase();
        s.toLowerCase();
        s.replaceAll("b", "replacement");<>//这个方法中,"b"是匹配模式,即所有"b"都会被替换成"replacement"<>

不同赋值方式

如果是通过新建String类的对象的方式新建字符串,那么新建一个内存里就会有一个新地址,举例:

String s1= new String{'a','b'};
String s2 = new String{'a','b'};
s1 == s2 //为false;

但如果是使用字面量,那么这就是常量,存放在方法区内,无论变量名称什么样,只要字符串一样,就是一样的地址,举例:

String s1= "ab";
String s2 = "ab";
s1 == s2 为true;

不可变性

String的底层是一个不可变的字符数组。

    private final char value[];

如果发生变化,即使长度一致,也要更改内存地址。

        String s1 = "abc";
        String s2 = s1;
        s2 = "mbc";
        //结果为false
        System.out.println(s2 == s1);

String对象建立后,如果再增加或减少,就需要新建一个对象,也就是变更内存地址。这样,使用String类拼接字符串,就是新建一个String对象。举例:

        String s1="a";
        for (int i=0; i<10;i++) {
            s1+=i;
        }

这里总共新建了12个对象,因为建s1的时候现在内存里新建了字符’a’,再新建字符串"a",在循环里又新建了10个对象,如果是StringBuilder,那么就只有2个。

StringBuilder的可变性

修改后仍然是同一个对象
StringBuilder的无参构造器的默认容量为16。

    public StringBuilder() {
        super(16);
    }

StringBuilder的有参构造器在默认容量16的基础上加上参数的长度。

    public StringBuilder(String str) {
        super(str.length() + 16);
        append(str);
    }

StringBuilder的append方法调用父类AbstractStringBuilder的append方法,返回的是当前对象,也就是说更改StringBuilder后仍然是原对象。

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

AbstractStringBuilder用字符数组value来存储变量,用count来记录数组内有多少字符。

    char[] value;
    int count;

append方法先调用ensureCapacityInternal方法保证value没有越界,再调用String的getChars方法将新的元素添加到value数组里。

    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;
    }

String的getChars方法利用System.arraycopy方法将新增的字符串复制到value数组的末尾。

    public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
    }

扩容
minimumCapacity就是count加上新增字符串长度的和,如果minimumCapacity减value数组长度大于0,说明容量不够。用Arrays.copyOf方法来对数组扩容,

    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

新的容量是原有长度乘2再加2,如果还是不够,就把长度设为minCapacity。位移运算可以提升性能,但可能会把容量变成负数,所以在return的时候需要检查newCapacity是不是小于等于0。在return的时候,还要检查新的容量是否越过Integer的边界,如果越界调用hugeCapacity方法。

   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;
    }

MAX_ARRAY_SIZE属性是Integer最大长度减8。如果原有的容量超过Integer的边界,直接抛异常。如果没有越界,判断原有的容量比MAX_ARRAY_SIZE大,就返回原有的容量,否则返回MAX_ARRAY_SIZE。

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    
    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

StringBuffer也是可变的。StringBuffer的底层在StringBuilder的基础上加上了synchronized关键字,也就是说StringBuffer的方法都是同步的,其余一样。

   public synchronized int length() {
        return count;
    }

常用方法:

        StringBuilder s = new StringBuilder("abcd");
        s.append(1);
        s.delete(0, 1);
        s.reverse();
        s.insert(0, "v");
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值