String、StringBuffer、StringBuilder的比较、及参数传递问题

1、String和StringBuffer的区别

String是内容不可变的,而StringBuffer内容是可变的,相当于一个容器可以存放字符串类型数据。具体可以通过源码来理解这两个类

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];	
     private int hash; 
    //中间省略N行代码
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
}

从源码中可以看出,String类被final修饰,并且里面还有一个被final修饰的数组。用final修饰的对象值可变,引用却不可变,即value数组的值是可变的,但因为由private对这个数组进行了封装,使得数组的值也不可变。
其实StringBuffer对象的底层也是一个char[]数组,但是没用用final修饰,所以值是可变的。

2、关于StringBuffer和String的参数传递

String作为参数传递的时候是和基本类型一样的,是一种特殊的引用类型,对象是字面值常量,没办法通过参数传递来改变字符串变量。而StringBuffer作为参数传递的时候和所有的引用类型的传递是一样的。

public class StringBufferTest{
	public static void main(String[] args){
		String s1 = "hello";
		String s2 = "world";
		System.out.println(s1+"--"+s2);//hello--world
		change(s1,s2);
		System.out.println(s1+"--"+s2);//hello--world
		
		StringBuffer sb1 = new StringBuffer("hello");
		StringBuffer sb2 = new StringBuffer("world");
		System.out.println(sb1+"--"+sb2);//hello--world
		change(sb1,sb2);
		System.out.println(sb1+"--"+sb2);//hello--worldworld
	}
	public static void change(String s1,String s2){
		s1 = s2;
		s2 = s1 + s2;	
	}
	public static void change(StringBuffer sb1,StringBuffer sb2){
		sb1 = sb2;
		sb2 = sb1 + sb2;
	}
}

通过上述例子可以看出:、

  • 对于String类型
    当调用chang方法之后是s1和s2并未变化,其实他和基本类型的转递是一样的,即当s1和s2传到change方法时候,change方法在栈上复制了一份常量值而不是引用,所有的操作最终都在栈上进行,当方法调用完毕后,change方法就消失,原来main方法里的s1和s2指向的常量池中的并没有改变。具体可以调试看看main里和change()中的变化
    在这里插入图片描述
  • 对于StringBuffer类型
    当调用change方法后,sb1和sb2的引用会被复制一份给方法里的局部变量sb1和sb2,这两个局部变量操作的对象和main中的s1和s2操作的是同一个对象,所以当调用结束后main中的变量所指的对象也就发生了变化。
    在这里插入图片描述
3、StringBuffer和String的相互转换
  • String 转换为 StringBuffer

方式一:通过构造方法

String str = "hello";
//注意不能把字符串的值直接赋值给StringBuffer
StringBuffer sb = new StringBUffer();

方式二:借助 append() 方法

String str2 = "world"
StringBuffer sb2 = new StringBuffer();
sb2.append(str2);
  • StringBuffer 转换为 String
    方式一:通过构造方法
    StringBuffer bf = new StringBuffer("java"); // 创建字符串缓冲区
    方式二:通过 toString() 方法
    String str = bf.toString();
4、关于StringBuilder

通过查看API:
一个可变的字符序列。 此类提供与StringBuffer的API,但不保证同步。 此类设计用作简易替换为StringBuffer在正在使用由单个线程字符串缓冲区的地方(如通常是这种情况)。 在可能的情况下,建议使用这个类别优先于StringBuffer ,因为它在大多数实现中将更快。

以上有两条重要信息:
StringBuilder和StringBuffer提供的功能方法是完全相同的
StringBuilder不保证同步,所以单线程下效率高,也就是他是线程不安全的

三者区别小结:

  • String是内容不可变的,而StringBuffer,StringBuilder都是内容可变的
  • StringBuffer是同步的,在多线程下数据安全,效率低;StringBuilder在多线程下数据不安全,效率高
  • StringBuffer和数组都可以看成容器,但是StringBuffer所存放的数据最终是字符串数组,而数组可以放多种,但必须是同一种数据类型
发布了52 篇原创文章 · 获赞 6 · 访问量 1461

猜你喜欢

转载自blog.csdn.net/qq_40488936/article/details/103541260
今日推荐