String StringBuffer StringBuilder关系总结

1.String类

String类没有apprend方法

String类的底层是通过char数组来保存字符串的。

StringBuffer类与StringBuilder类调用toString()方法可直接转为String类对象

String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。且String类是被final修饰的,所以它不能被重写。

String a = “a”; //假设a指向地址0x0001
a = “b”;//重新赋值后a指向地址0x0002,但0x0001地址中保存的"a"依旧存在,但已经不再是a所指向的,a 已经指向了其它地址。

因此String的操作都是改变赋值地址而不是改变值操作。

即对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象来覆盖原来的对象。

源码如下:

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
    }
 
 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);
    }
 
 public String replace(char oldChar, char newChar) {
    if (oldChar != newChar) {
        int len = count;
        int i = -1;
        char[] val = value; /* avoid getfield opcode */
        int off = offset;   /* avoid getfield opcode */
 
        while (++i < len) {
        if (val[off + i] == oldChar) {
            break;
        }
        }
        if (i < len) {
        char buf[] = new char[len];
        for (int j = 0 ; j < i ; j++) {
            buf[j] = val[off+j];
        }
        while (i < len) {
            char c = val[off + i];
            buf[i] = (c == oldChar) ? newChar : c;
            i++;
        }
        return new String(0, len, buf);
        }
    }
    return this;

注意

String str1 = “hello world”;和String str3 = “hello world”; 都在编译期间生成了 字面常量和符号引用,运行期间字面常量"hello world"被存储在运行时常量池(当然只保存了一份)。

通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。

故str1==str3返回是为true的。

思考

1.String str = new String(“abc”); 创建了几个对象

分两种情况:

1.如果 abc 字符串之前没有用过,这毫无疑问创建了两个对象,一个是new String 创建的一个新的对象,一个是常量“abc”对象的内容创建出的一个新的String对象。

2.如果abc 字符串被引用,根据常量池的原理,则只会创建一个对象。

2.StringBuffer类

有apprend方法

StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。 每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量。

StringBuffer 中append方法底层实现

思路:通过复制数组扩大char[]的容量,完成字符的拼接(就是把新的字符追加到char[])。如果要返回String类型,可以调用toString方法生成一个String方法。

java.lang.AbstractStringBuilder#append(java.lang.String)源码如下:

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

参考: StringBuffer 中append方法底层实现 https://www.cnblogs.com/zhangit/p/7886295.html

3.StringBuilder类

有apprend方法如

StringBuilder sh=new StringBuilder("jh");
sh.append("hahj");
System.out.println(sh);

输出为:jhhahj

StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的

常见例子

package com.test;

public class testString {
	public static void main(String[] args) {
		StringBuffer a=new StringBuffer("A");
		StringBuffer b=new StringBuffer("B");
		testString t=new testString();
		t.print(a, b);
		System.out.println(a+","+b);
		String c="fa";
		String d="faa";
		//String可以像基本数据那样用“=”赋值
		d=c;
		System.out.println(d);
	}
	public  void print(StringBuffer x,StringBuffer y){
		x.append(y);
//		y=x;
		//x.append(y)没有返回值
		y=x.append(y);
		
	}
}

输出结果为:
ABB,B
fa

4.总结

1.StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,而string是final修饰的,会创建新的对象。
2.如果是高并发下,且操作全局变量应该使用StringBuffer,方法内的局部变量用StringBuilder,因为栈内存是线程私有的。

参考资料

1、探秘Java中的String、StringBuilder以及StringBuffer https://www.cnblogs.com/dolphin0520/p/3778589.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值