七、java中的字符串(String、StringBuilder、StringJoiner)

字符串

  • 七、字符串
    • 1.String类
      • 1.1 特点
      • 1.2 构造方法
      • 1.3 成员方法
      • 1.4 创建对象方式的区别
      • 1.5 字符串的比较
        • 1.5.1 ==号的作用
        • 1.5.2 equals方法
    • 2. StringBuilder
      • 2.1 构造方法
      • 2.2 成员方法
    • 3. StringJoiner
      • 3.1 构造方法
      • 3.2 成员方法
    • 4. 字符串原理

具体信息请查看 API 帮助文档

七、字符串

1.String类

​ String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。Java 程序中所有的双引号字符串,都是 String 类的对象。

String 类在 java.lang 包下,所以使用的时候不需要导包!

1.1 特点

  1. 不可变性:String对象在创建后不可被修改。

     这意味着一旦一个String对象被赋值,它的值就不能再被改变。
    
     如果我们对一个String对象执行任何的修改操作,实际上是创建了一个全新的String对象来存储修改后的值。
    
     这样的设计是为了提高性能和安全性,因为不可变的String对象可以在多线程环境下共享而不会出现意外的修改。
    
  2. 字符串字面量:Java提供了字符串字面量的方式来表示String对象。

     字符串字面量是用双引号括起来的字符序列,例如:"Hello"。
    
     字符串字面量在编译时就会自动优化为String对象,可以直接使用,而不需要显式的调用构造函数。
    
     此外,多个字符串字面量可以通过"+"运算符连接起来,形成一个新的String对象。
    
  3. 字符编码:String类使用UTF-16编码(Unicode字符集的一种)来表示字符串,每个字符占用16位。

     我们可以通过`getBytes()`方法将字符串转换为指定的字符编码(如UTF-8)
    
  4. 字符串池:为了提高性能和节省内存,Java使用了字符串池的概念。

     字符串池是一个字符串缓存区域,存储着已经创建的字符串对象。
    
     当我们创建新的字符串对象时,首先会检查字符串池中是否已存在相同内容的字符串。
    
     如果存在,则返回池中的引用,而不会创建新的对象。
    
     这样可以减少内存消耗和垃圾回收的开销,提高程序的性能。
    
  5. 运算符重载:String类重载了加号"+"运算符,可以用于连接多个字符串。

     这个特性使得字符串拼接变得简洁和直观,例如:"Hello" + "World"将会得到一个新的字符串"HelloWorld"。
    
  6. 性能优化:由于String对象的不可变性,它们在多线程环境下是安全的并且可以被共享。

     这样可以避免许多并发问题,并提高程序的性能。
    
  7. 字符串拼接性能优化:在需要频繁拼接字符串的场景下,使用StringBuilder类或StringBuffer类可以提升性能。

     `StringBuilder`和`StringBuffer`是可变的字符序列,可以在原地修改字符串,而不需要创建新的对象。	
     
     `StringBuilder`是线程不安全的,适用于单线程环境。
    
     StringBuffer`是线程安全的,适用于多线程环境。
    

1.2 构造方法

  • 常用的构造方法
方法名 说明
public String() 创建一个空白字符串对象,不含有任何内容
public String(char[] chs) 根据字符数组的内容,来创建字符串对象
public String(byte[] bys) 根据字节数组的内容,来创建字符串对象
String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc
  • 示例代码
public class StringDemo01 {
    public static void main(String[] args) {
        //public String():创建一个空白字符串对象,不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1);

        //public String(char[] chs):根据字符数组的内容,来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2);

        //public String(byte[] bys):根据字节数组的内容,来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3);

        //String s = “abc”;	直接赋值的方式创建字符串对象,内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4);
    }
}

1.3 成员方法

方法名称 描述
char charAt(int index) 返回指定索引处的 char 值。
int compareTo(String anotherString) 按字典顺序比较两个字符串。
int compareToIgnoreCase(String str) 按字典顺序比较两个字符串,不考虑大小写。
boolean equals(Object anObject) 将此字符串与指定的对象比较。
boolean equalsIgnoreCase(String anotherString) 将此 String 与另一个 String 比较,不考虑大小写。
void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此字符串复制到目标字符数组。
int length() 返回此字符串的长度。
String replace(char oldChar, char newChar) 返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String substring(int beginIndex) 返回一个新的字符串,它是此字符串的一个子字符串。
String substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串的一个子字符串。
String toString() 返回此对象本身(它已经是一个字符串!)。

这些方法均属于String类中的实例方法,用于操作字符串。具体来说:

- `charAt(int index)`方法用于获取指定索引位置上的字符。

- `compareTo(String anotherString)`方法用于比较两个字符串,按字典顺序比较。

- `compareToIgnoreCase(String str)`方法与`compareTo`方法类似,但不考虑大小写。

- `equals(Object anObject)`方法用于判断当前字符串是否与指定的对象相等。

- `equalsIgnoreCase(String anotherString)`方法与`equals`方法类似,但不考虑大小写。

- `getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)`方法用于将当前字符串中指定范围的字符复制到目标字符数组中。

- `length()`方法用于获取当前字符串的长度。

- `replace(char oldChar, char newChar)`方法用于替换当前字符串中指定字符的值。

- `substring(int beginIndex)`方法用于获取当前字符串中子串,从指定索引位置开始到结尾。

- `substring(int beginIndex, int endIndex)`方法用于获取当前字符串中子串,从指定开始索引位置到指定结束索引位置的子串。

- `toString()`方法用于将当前对象转换为字符串,该方法的实现返回当前对象本身,因为`String`本身就是一个字符串。

1.4 创建对象方式的区别

  • 通过构造方法创建

    ​ 通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同

  • 直接赋值方式创建

    ​ 以“ ”方式给出的字符串,只要字符串相同,JVM 都只会建立一个 String 对象,并在字符串池中维护

1.5 字符串的比较

1.5.1 ==号的作用
  • 比较基本数据类型:比较的是具体的值
  • 比较引用数据类型:比较的是对象地址值
1.5.2 equals方法
  • 方法介绍

    public boolean equals(String s)     比较两个字符串内容是否相同、区分大小写
    

    示例代码:

    public class StringDemo02 {
        public static void main(String[] args) {
            //构造方法的方式得到对象
            char[] chs = {'a', 'b', 'c'};
            String s1 = new String(chs);
            String s2 = new String(chs);
    
            //直接赋值的方式得到对象
            String s3 = "abc";
            String s4 = "abc";
    
            //比较字符串对象地址是否相同
            System.out.println(s1 == s2);//false
            System.out.println(s1 == s3);//false
            System.out.println(s3 == s4);//true
            System.out.println("--------");
    
            //比较字符串内容是否相同
            System.out.println(s1.equals(s2));//true
            System.out.println(s1.equals(s3));//true
            System.out.println(s3.equals(s4));//true
        }
    }
    

2. StringBuilder

2.1 构造方法

  • 空参构造
StringBuilder stringBuilder=new StringBuilder();
  • 带参构造
StringBuilder stringBuilder=new StringBuilder("aaaa");

2.2 成员方法

  • append() :添加StringBuilder的内容

  • reverse() :反转StringBuilder的内容

  • length() :获取StringBuilder的长度

  • toString(): 转换成字符串

      (因为StringBuilder是一个长度可变容器,需要将最后结果转换成字符串,字符串长度固定,不可变)
    

注意:StringBuilder打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理

	StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。

例如:

public class StringBuilderDemo3 {
    public static void main(String[] args) {
        //1.创建对象
        StringBuilder sb = new StringBuilder("abc");

        //2.添加元素
        /*sb.append(1);
        sb.append(2.3);
        sb.append(true);*/

        //反转
        sb.reverse();

        //获取长度
        int len = sb.length();
        System.out.println(len);

        System.out.println(sb);
    }
}

3. StringJoiner

3.1 构造方法

  • StringJoiner stringJoiner=new StringJoiner(“delimiter”);

    delimiter:间隔符号
    
  • StringJoiner stringJoiner=new StringJoiner(“delimiter”,“prefix”,“suffix”); 、

    delimiter:间隔符号;prefix:开始符号;suffix:结束符号;
    

3.2 成员方法

  • add() 添加StringJoiner的内容

  • length() 获取StringJoiner的长度

       注意:长度为所有的字符的长度,包括间隔符号,开始符号,结束符号
    
  • toString() 转换成字符串

      (因为StringJoiner是一个长度可变容器,需要将最后结果转换成字符串,串长度固定,不可变)
    

注意:StringJoiner打印的不是地址值而是属性值,因为其是java已经写好的类,在底层对其进行了一些处理

例如:

//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);//aaa---bbb---ccc
//1.创建对象
StringJoiner sj = new StringJoiner(", ","[","]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);//15
//3.打印
System.out.println(sj);//[aaa, bbb, ccc]
String str = sj.toString();
System.out.println(str);//[aaa, bbb, ccc]

4. 字符串原理

  1. 字符串存储的内存原理

    • 直接赋值会复用字符串串池中的
    • new出来的不会复用,而是开辟一个新的空间
  2. ==号比较的到底是什么?

    如果比较的是基本数据类型:比的是具体的数值是否相等。

    如果比较的是引用数据类型:比的是地址值是否相等。

  3. 字符串拼接的底层原理

    • 字符串拼接包含变量:

      当字符串拼接包含变量时,使用+运算符进行拼接,底层会使用StringBuilder类来执行拼接操作。

      StringBuilder类在拼接变量时,会将变量的值转换为字符串并追加到当前的StringBuilder对象中。

      例如:

      String name = "Alice";
      int age = 25;
      String message = "My name is " + name + " and I am " + age + " years old.";
      

      这段代码编译后的实际执行是:

      StringBuilder sb = new StringBuilder();
      sb.append("My name is ");
      sb.append(name);
      sb.append(" and I am ");
      sb.append(age);
      sb.append(" years old.");
      String message = sb.toString();
      

      可以看到,变量名和值都被转换为字符串,并追加到StringBuilder对象中,然后通过toString()方法得到最终的拼接结果。

    • 字符串拼接不包含变量:

      当字符串拼接不包含变量时,使用+运算符进行拼接,底层会直接进行字符串的连接操作。

      由于没有变量,编译器可以在编译时确定整个拼接结果。

      例如:

      String str1 = "Hello";
      String str2 = "World";
      String result = str1 + ", " + str2;
      

      这段代码编译后的实际执行是:

      String result = "Hello, " + "World";
      

      可以看到,编译器直接将不同字符串字面量连接在一起,形成最终的拼接结果。

  4. StringBuilder提高效率原理

    • 可变性:StringBuilder是可变的字符序列,可以在原地修改字符串内容。相比于String类的不可变性,使用StringBuilder可以避免频繁创建新的字符串对象。

    • 内部缓冲区:StringBuilder内部使用一个可扩展的字符数组作为缓冲区,用于存储字符串的内容。在进行字符串拼接时,StringBuilder会将新的字符追加到缓冲区中。

    • 避免创建中间对象:当使用+运算符或concat()方法进行字符串拼接时,每次拼接都会创建一个新的字符串对象。而StringBuilder则避免了这一点,在进行拼接操作时直接在缓冲区中修改字符串内容,避免了频繁创建新的字符串对象。

       需要注意的是,`StringBuilder`是非线程安全的。
      
       如果在多线程环境下进行字符串操作,应该使用线程安全的`StringBuffer`类来替代`StringBuilder`。		
      
       `StringBuffer`的使用方式和`StringBuilder`类似,但具备线程安全的特性。
      

具体信息请查看 API 帮助文档

你可能感兴趣的:(Java,java,开发语言)