String StringBuffer StingBuilder --面试复习6.28-6.29
1、Sting有两种创建方式:
String str = "lele"; 直接赋值,先在字符串常量池中查找有无”lele“,若有则str直接引用它,没有则先创建后引用;
String str = new String("lele");通过构造器进行创建。此时先在堆中创建一个空间,由这个空间指向常量池中的”lele”,若常量池中没有,则先创建后引用,所以,str是直接指向堆中的空间,再有堆中的空间指向“lele”,str->堆->常量池;
2、String的常用方法:indexOf(str)查找字符串第一次出现位置;lastIndexOf(str)查找字符串最后一次出现位置;substring(start,end)获取从start到end的字串 [ ); trim() 返回去除前后空格的子串;charAt( index) 获取获取字符串指定位置字符;
2.1split(regex,limit)根据regex(正则表达式)对字符串进行分割并返回分割后的字符串数组,limit控制模式匹配使用的次数,当limt>0时,会分割最多limit-1次,若limit-1小于字符串中符合正则匹配式的数量,则分割后最后一个字符串包含剩余所有字符;当limt = 0时,会根据正则对字符串进行分割,同时去除字符串末尾的空元素。当limit匹配将应用尽可能多的次数,而且数组的长度是任何长度。
当regex匹配失败时,返回原字符串。
浅析split()源码:
3、字符串的不可变性 String对象一旦被创建则不可修改,对其进行的连接,重新赋值等操作实际上是创建了新的对象(存储空间改变),旧对象会被GC;
String被final修饰,被final修饰的类只能保证不被继承,并且该类对象在对空间的地址不会改变。但是String对象的引用可变,可以指向其他对象。
String本质是一个被final修饰的char数组,char数组的引用不可变,但是可以通过修改char[index] = “ ”来修改字符串的值,但是String内部并不提供此操作,保证了String的不可变。
数组引用不可变,数组中数据的引用可变。
4、字符串的连接
String s1 = "a"; String s2 = "a"; String s3 = "a" + s2; String s4 = "a" + "a"; String s5 = s1 + s2; //表达式只有常量时,编译期完成计算 //表达式有变量时,运行期才计算,所以地址不一样 System.out.println(s3 == s4); //f System.out.println(s3 == s5); //f System.out.println(s4 == "aa"); //t
5、String StringBuffer StringBuilder的区别
String被声明为final class,是不可变的,也是线程安全的,当对String对象进行更新时,实际上是创建了一个新的对象,产生一个新的引用,旧的对象会被回收,在对String进行操作时,可能会产生很多无用的中间对象,频繁进行这种操作会对性能产生影响。
StringBuffer保存字符串变量,每次StringBuffer的更新,引用不变。提供了append()和insert()方法,可以将字符串添加到末尾或者指定位置插入,它的本质是线程安全的可修改的字符序列,将所有修改数据的方法都加上了synchronized。
StringBuilder和StringBuffer类似,本质上没什么区别,去除了线程安全,减小了开销。
StringBuffer 和 StringBuilder 二者都继承了 AbstractStringBuilder ,底层都是利用可修改的char数组(JDK 9 以后是 byte数组)。
/**源码解释
StringBuilder:一个可变的字符序列,提供了与StringBuffer兼容的API,但是不能保证线程安全,String Builder被设计用来替代单线程状态下的StringBuffer。不过大多数情况下都推荐使用StringBuffer因为它是线程安全的。
StringBuilder最重要的操作是append()和insert()方法;能够将给予的有效数据添加或插入到已有的字符序列。
每个StringBuilder都有一个capacity(容量),当字符序列超过此容量时,会进行自动扩容,对于多线程而言,String Builder是不安全的,推荐使用StringBuffer。
StringBuffer:线程安全的可变字符序列,类似String,但是,字符序列通过包含的方法可以改变。StringBuffer对于多线程是安全的,方法的执行都是同步的,各个线程对方法的调用顺序和对特定实例的行为操作是一致的。
StringBuffer最重要的操作是append()和insert()方法;能够将给予的有效数据添加或插入到已有的字符序列。
当涉及到对原字符序列的操作时,会在string buffer 中执行,不会对原数据进行操作,
每个StringBuffer都有一个capacity(容量),当字符序列超过此容量时,会进行自动扩容,对于多线程而言,String Builder是不安全的,推荐使用StringBuffer。
*/
StringBuffer 常用方法介绍(StringBuilder和其相同):
对StringBuffer初始化有四种方式,1、直接创建不赋值,此时会给StringBuffer一个默认capacity 16;2、创建时给定一个int参数,作为Stringbufferd的初始容量;3、创建时给定一个字符串,此时容量为字符串长度+16;4、通过CharSequence对象作为参数,容量为CharSequence对象长度+16,若其对象为空,容量仍默认16。
ps:CharSequence(字符序列,描述字符串的一些信息的接口,提供了如length(),charAt(),toString(),subSequence()方法,String、StringBuffer、StringBuilder都对其进行了实现,可简单理解为一个字符串)
append()方法调用过程解释:
insert()调用: