Java高级-String、StringBuffer和StringBuilder

目录

String

StringBuffer与StringBuilder

StringBuffer

StringBuilder

使用总结


 

String

1.概念     

       java.lang.String表示字符串,属于引用数据类型,是final类型的,即不可变的。并且不能继承、不能修改这个类。源码如下:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    //...
}

2.特性

1.String不适合于频繁修改。一般为了提高效率节省空间,使用StringBuff.
2.String在内存中采用Unicode编码方式,任何一个字符对应两个字节的定长编码。

3.使用

方式一:String s = "abc";
方式二:String s = new String("abs");

4.字面量

       字面量就是常量

5.String常量池

          出于性能考虑,为了避免在一个系统中产生大量的String对象,JVM会将字符串字面量对象缓存在常量池中(常量池可以理解为String[]数组)。         

          所以,创建一个字符串时,JVM首先会在池中检查是否有值相同的字符串对象,若存在则返回该对象的引用;如果没有则新建字符串对象,返回对象的引用,并且将新创建的对象放入池中。但是,通过new方法创建的String对象是不检查字符串常量池的,而是直接在堆中创建新对象,也不会把对象放入池中上述原则只适用于直接给String对象引用赋值的情况。       

        如下所示:

public class Test{
    public static final HELLO = "hello";

    public static void main(String[] args){
        String s1 = "123hello";
        String s2 = "123hello";
        String s3 = "123" + "hello";
        String s4 = 1 + 2 + 3 + "hello";
        String s5 = "1" + 2 + 3 + "hello";
        String s6 = '1' + '2' + '3' + "hello";
        //通过new方式创建String对象不检查常量池
        String s7 = new String("123hello");
        String a = "123";
        String b = "hello";
        String s8 = a + b;
        String s9 = "123" + b;
        String s9 = "123" + HELLO;
        System.out.println(s2 == s1);  //返回true
        System.out.println(s3 == s1);  //返回true,在编译时s3变为123hello
        System.out.println(s4 == s1);  //返回false,s4为6hello
        System.out.println(s5 == s1);  //返回true,s5为123hello
        System.out.println(s6 == s1);  //返回false
        System.out.println(s7 == s1);  //返回false,重新创建一个String对象
        System.out.println(s8 == s1);  //返回false,a和b属于变量,不会检查常量池
        System.out.println(s9 == s1);  //返回false,b属于变量,不会检查常量池
        System.out.println(s10 == s1); //返回true,HELLO属于常量
    }
}

6.常用API

  • public boolean equals(Object anObject)

         String的equals方法继承自Object,并且重写了该方法,比较两个字符串的内容(字符串序列)是否相同,相同返回true;否则返回false。

         注意:==比较的是地址,equals比较的是内容。        

        源码如下:

 public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
}
  • public boolean equalsIgnoreCase(String anotherString)

           equlasIgnoreCase跟equals比较的都是字符串的内容,只是equlasIgnoreCase会忽略字符串的大小写。源码如下所示:

 public boolean equalsIgnoreCase(String anotherString) {
    return (this == anotherString) ? true : (anotherString != null)
        && (anotherString.value.length == value.length)
        && regionMatches(true, 0, anotherString, 0, value.length);
}
  • int indexOf(...)

        返回检索的索引下标。

  • String trim()

        返回去掉首尾空白字符后的字符串。

  • 截取字符串
String substring(int formIndex) 返回从给定索引位置formIndex开始到字符串结尾的子字符串
String substring(int formIndex, int endIndex) 返回从formIndex到endIndex-1的子字符串
  • char[] toCharArray()

         返回字符串内部维护的字符数组。

  • 分割字符串

1.public String[] split(String regex)

将当前字符串按照给的的正则表达式格式进行分割,返回一个分割后的String数组
2.public String[] split(String regex, int limit)  

       注意事项:

注意点1:
String str = ",1,2,";
System.out.println(Arrays.toString(str.split(","));
输出结果为:
[,1,2]

注意点2:
String str = ".1.2.3.";
System.out.println(Arrays.toString(str.split("\\.")); //要使用转义字符\
输出结果为:
[,1,2,3]

注意点3:切割空白字符
String str = " 1  2    3 ";
System.out.println(Arrays.toString(str.split("\\s+")); 
输出结果为:
[,1,2,3]
  • 替换字符串
1.public String replaceAll(String regex, String replacement)

将当前字符串按照给的的正则表达式和给定的替换内容

进行替换,返回替换后的新字符串。

  • 还有很多常用API......

        

StringBuffer与StringBuilder

1.相同

1.和String不同的是,StringBuffer和StringBuilder封装可变的字符串。
2.StringBuffer和StringBuilder就是为了解决大量拼接字符串时产生很多中间对象问题的一个类。提供append和add,可以将字符串添加到已有字符串序列的末尾或指定位置。即对象创建后可由通过调用方法改变其封装的字符串序列。

3.StringBuffer和StringBuilder二者都继承了AbstractStringBuilder,底层都是利用可修改的char数组(JDK9以后是byte数组)。

所以如果有大量的字符串拼接,如果能预知大小的话最好在new StringBuffer 或者StringBuilder 的时候设置好capacity,避免多次扩容的开销。扩容要抛弃原有数组,还要进行数组拷贝创建新的数组。

2.不同

  • StringBuffer是线程安全的,增加了开销;StringBuilder是JDK1.5发布的,是线程不安全的,减少了开销。

StringBuffer

1.本质

         StringBuffer本质是一个线程安全的可修改的字符序列,把所有修改数据的方法都加上了synchronized。但是保证了线程安全是需要付出代价的。

2.常用API

        跟StringBuilder一样

StringBuilder

1.使用

//构造方法StringBuilder()将创建不含任何字符序列的StringBuilder对象(为空字符串"")
StringBuilder sb = new StringBuilder();
//构造方法StringBuilder(String str)将创建含str字符序列的StringBuilder对象
StringBuilder sb = new StringBuilder("字符串”);

2.常用API

  • append(追加)
  • delete(移除)
  • insert(插入)
  • reserve(反转)
  • replace(替换)
public StringBuilder replace(int start,int end,String str)

使用给定 String 中的字符替换此序列的子字符串中的字符。

该子字符串从指定的 start 处开始,一直到索引 end - 1 处的字符

使用总结

  • 在字符串不经常发生变化的业务场景优先使用String。如常量的声明,少量字符串操作(拼接、删除等)
  • 在单线程情况下,如果有大量字符串操作情况,应该使用StringBuilder。不能使用String"+"来拼接而是使用,避免产生大量无用的中间对象,耗费空间且执行效率低下(新建对象、回收对象花费大量时间)。如JSON的封装等。
  • 在多线程情况下,如果有大量字符串操作情况,应该使用StringBuffer。如Http参数解析和封装。

参考:https://baijiahao.baidu.com/s?id=1629804867201303563&wfr=spider&for=pc

发布了131 篇原创文章 · 获赞 39 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_35507234/article/details/96476324