在java编程中字符串属于对象,StringBuilder、 StringBuffer、 String是java中常用的对字符串操作的类,那么他们什么不同呢?
String
String 类以及它的value都是final修饰的,表明String类是无法被继承的,value是无法被改写的,不存在扩容。String由于它的不可变性,对其进行拼接、截取等操作都会产生新的对象,频繁操作字符串效率低下,因中间对象太多,造成内存空间浪费(JDK8开始,String的操作会被编译成StringBuilder)。
创建一个字符串时,首先会检查常量池中是否有值相同的字符串对象,如果有就直接返回引用,不会创建字符串对象,如果没有则新建字符串对象,返回对象引用,并且将新创建的对象放入池中。但是通过new方法创建的String对象是直接在堆中创建新对象。
例:
String str = "abdc";
执行以上代码,会先检查在字符串常量池里是否有"abdc"对象,如果有str直接指向该引用,如果
没有就创建一个"abdc"对象,再将str指向该引用。
str = "hello";
这时str的值改变了,这里的改变是str指向的引用变了,首先会检查字符串常量池中是否有"hello"
对象,没有就创建一个该对象,然后将str指向该引用
String str1 = new String(“abdc”);
执行以上代码,会生成两个对象,一个是会检查常量池中是否有"abdc"的对象,没有就创建一个并
放入常量池,另一个是会在堆中创建一个"abdc"对象,str1就指向堆中的"abdc"对象。
java为解决String类大量操作字符串效率低下问题,引入率StringBuilder和StringBuffer两个类。
StringBuilder
StringBuilder类内部维护的是可变长度的char[],存在扩容,其append拼接字符串方法内部调用System的native方法,进行数组的拷贝,不会重新生成新的StringBuilder对象。它是非线程安全的字符串操作类,其每次调用toString方法而重新生成的String对象,不会共享StringBuilder对象内部的char[],会进行一次char[]的copy操作。
StringBuffer 类内部维护可变长度char[],基本上与String一致,区别在于其是线程安全的字符串操作类,大部分方法都采用了Synchronized关键字修改,以此来实现在多线程下的字符串操作的安全性。其toString方法而重新生成的String对象,会共享StringBuffer对象中的toStringCache属性,但是每次的StringBuffer对象修改,都会置空该属性的值。
继承关系
String实现了CharSequence和Serializable
StringBuffer和StringBuilder都继承AbstractStringBuilder,而AbstractStringBuilder
实现了CharSequence和Appendable
相关知识
==和equals对比
== :
基本数据类型(byte,short,char,int,float,double,long,boolean):比较的是值
是否相同
引用数据类型:比较的是地址值是否相同
equals的作用:
引用类型默认比较的是地址值,但是在一些类库中已经重写了该方法,重写该方法一般用来比较对象
的成员变量值是否相同,如String, Integer, Date等类中,所以它们不再是比较类在堆中的地址了。
例:
String str1 = new String(”fd”);
String str2 = new String(”fd”);
str1==str2;的值是false,因为==比较的是对象的地址,他们的地址是不同的,值相同。
String str1 = ”fd”;
String str2 = ”fd”;
str1==str2;的值是true,因为他们都是指向字符串常量池中同一个对象,所以是相同的地址。