深入String、StringBuilder、StringBuffer
目录:
1.String
2.StringBuilder和StringBuffer
3.String、StringBuild、StringBuffer区别
1.String
(1)String的基本用法:
indexOf():返回指定字符的索引。 charAt():返回指定索引处的字符。 replace():字符串替换。 trim():去除字符串两端空白。 split():分割字符串,返回一个分割后的字符串数组。 getBytes():返回字符串的 byte 类型数组。 length():返回字符串长度。 toLowerCase():将字符串转成小写字母。 toUpperCase():将字符串转成大写字符。 substring():截取字符串。 equals():字符串比较。(2)String的特点
1.String不是基本数据类型,String 底层是一个 char 类型的数组
2.使用 final 来定义 String 类,表示 String 类不能被继承
3.String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用。
4.String内容是不可变的但不代表引用不可以变,String 是只读字符串,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象。不变模式的主要作用在于当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性。
前两点可以通过源码来解释:
这个第3,4点怎么理解呢,看个例子
答案是:
再细品这两句话
String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用
String内容是不可变的但不代表引用不可以变,String 是只读字符串,对它进行任何操作,其实都是创建一个新的对象(博主认为这个新的对象创建在堆区为啥呢看下图),再把引用指向该对象
如果c也在方法区那么为啥创建的新的四个ghjk为啥没有一个的引用和c一样
(3)字符串常量池
String是字符串常量那么什么是字符串常量池?
字符串常量池位于堆内存中,专门用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。
(4)两种创建字符串对象相同吗:String str="abc"与 String str=new String(“abc”)
答案当然是不一样,因为内存的分配方式不一样。
String str="abc"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“abc”) 则会被分到堆内存中(当然也没这么简单下面会讲)
(5)创建对象个数的问题:
String str=new String(“abc”)
其实这里有两种情况:
第一种当常量池没有“abc”这个字符串的话就创建两个对象
当常量池中没有字符串“abc”的时候那么创建一个对象在堆区,然后再在常量区创建一个字符串常量“abc”
博主你怎么知道你头大?
博主:没错我就是头大
兄弟们拿刀
博主:别别别,我好好讲还不行吗
我们都知道String本质还是一个字符串数组那么当我们再创建String b=“abc”(这里如果常量区有“abc”就把这个引用赋给b,没有就在常量区创建一个“abc对象”前面说了),由源码我们知道String本质其实是一个value[]的字符串数组,我们比较b的value和str的value发现他俩地址一样,这不就验证了我刚才创建两个的说法了吗
第二种当常量池有“abc”这个字符串的时候就创建一个对象
和上面一样只不过b=“abc”在str=new String之前一样去比较两个对象的底层数组得出创建一个对象
2.StringBuffer和StringBuilder
(1)
存在于java.lang.StringBuilder中,我们知道String是字符串常量,不可以改变指向的对象值,只能改变指向的对象,那么StringBuilder就不一样了,他是一个可变的字符串序列
原来StringBuilder是个字符串的缓冲区,即它是一个容器,容器中可以装很多字符串。并且能够对其中的字符串进行各种操作,它的内部拥有一个数组用来存放字符串内容,进行字符串拼接时,直接在数组中加入新内容。StringBuilder会自动维护数组的扩容原理如下:
(2)常用的方法:
运行结果:
这里注意append方法返回StringBuffer对象。toString()会把一个StringBuffer对象转换成一个String对象,一个StringBuffer对象的引用是不能等于一个String对象的
StringBuffer和StringBuilder两个用法差不多StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。
3.String、StringBuild、StringBuffer的区别
1.String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
2.每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
3.如果要操作少量的数据用 =》 String。
单线程操作字符串缓冲区 下操作大量数据 =》 StringBuilder。
多线程操作字符串缓冲区 下操作大量数据 = 》StringBuffer。
总结
以上是生活随笔为你收集整理的深入String、StringBuilder、StringBuffer的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 还在傻傻分不清楚equal和==
- 下一篇: Date、DateFormat、Cale