String

String

一、String 类

String 类是 Java 中用于表示字符串的核心类,其底层实现为不可变字符序列(一旦创建,内容无法修改)。

字符串创建

Java 提供了 4 种常见的字符串创建方式,具体实现如下:

public class StringBuild {

    public static void main(String[] args) {

        // 1.直接创建(推荐,会复用字符串常量池中的对象)
        String str1 = "abc";
        System.out.println(str1);

        // 2.新建对象创建(会创建两个对象:常量池中的"abc" + 堆中的String对象)
        String str2 = new String("abc");
        System.out.println(str2);

        // 3.通过字符数组创建
        char[] crr = new char[]{'a', 'b', 'c'};
        String str3 = new String(crr);
        System.out.println(str3);

        // 4.通过字节数组创建(字节对应 ASCII 码,97='a'、98='b'、99='c')
        byte[] brr = new byte[]{97 ,98 ,99};
        String str4 = new String(brr);
        System.out.println(str4);

    }

}

字符串查找

提供多种查找方法,支持查找单个字符或子字符串,支持正向/反向查找。

public class StringFind {

    public static void main(String[] args) {

        String str = "hello meat ooo";

        // 1. 查找指定索引的字符
        System.out.println(str.charAt(4));

        System.out.println("============================================================");

        // 2. 正向查找(从前往后)
        // 2.1 查找第一次出现指定字符的下标
        System.out.println(str.indexOf('o'));
        // 2.2 从指定索引开始,查找第一次出现指定字符的下标
        System.out.println(str.indexOf('a', 6));
        // 2.3 查找第一次出现指定字符串的第一个字符的下标
        System.out.println(str.indexOf("ooo"));
        // 2.4 从指定索引开始,查找第一次出现指定字符串的第一个字符的下标
        System.out.println(str.indexOf("ooo", 10));

        System.out.println("============================================================");

        // 3. 反向查找(从后往前)
        // 3.1 从后往前找第一次出现指定字符的下标
        System.out.println(str.lastIndexOf('t'));
        // 3.2 从指定索引开始,从后往前找第一次出现指定字符的下标
        System.out.println(str.lastIndexOf('t', 10));
        // 3.3 从后往前找第一次出现指定字符串的下标
        System.out.println(str.lastIndexOf("ooo"));
        // 3.4 从指定索引开始,从后往前找第一次出现指定字符串的下标
        System.out.println(str.lastIndexOf("ooo", 10));

    }
}

字符串比较

字符串比较分为引用地址比较内容比较,两种方式的用途不同。

public class StringMethod {

    public static void main(String[] args) {

        String str1 = new String("Hello");
        String str2 = new String("Hello");
        String str3 = new String("World");
        String str4 = str1;

        // 1. 比较引用地址(判断是否为同一个对象):==
        System.out.println(str1 == str2);  // false(不同对象,堆地址不同)
        System.out.println(str1 == str4);  // true(同一对象,引用地址相同)
        System.out.println("============================================================");

        // 2. 比较字符串内容(返回布尔类型):str1.equals(str2)
        System.out.println(str1.equals(str2)); // true(内容相同)
        System.out.println(str1.equals(str4)); // true(内容相同)
        System.out.println("============================================================");

        // 3. 比较内容(按字典序,返回整型):str1.compareTo(str2)
        // 返回 0:内容相同;返回正数:str1 > str2;返回负数:str1 < str2
        System.out.println(str1.compareTo(str2)); // 0
        System.out.println(str1.compareTo(str3)); // 负数(H < W)
        System.out.println("============================================================");

        // 4. 比较内容(忽略大小写,按字典序返回整型):str1.compareToIgnoreCase(str2)
        System.out.println(str1.compareToIgnoreCase(str2)); // 0
        System.out.println(str1.compareToIgnoreCase(str3)); // 负数
        System.out.println("============================================================");
    }
}

字符串替换

支持替换全部匹配内容或仅替换第一个匹配内容。

public class StringReplace {
    public static void main(String[] args) {
        String str = "Hello meat";

        // 1. 替换全部匹配的字符/字符串:str.replaceAll()
        System.out.println(str.replaceAll("l", "p"));
        // 2. 替换首个匹配的字符/字符串:str.replaceFirst()
        System.out.println(str.replaceFirst("l", "p"));
    }
}

字符串拆分

将字符串按指定分隔符拆分为字符串数组,支持限制拆分次数,特殊分隔符需要转义。

public class StringSpilt {
    public static void main(String[] args) {

        String str = "Hello World Hello meat";

        // 1. 将字符串全部以空格拆分,用字符串数组接收结果
        String[] srr1 = str.split(" ");
        for (String s : srr1) {
            System.out.println(s);
        }
        System.out.println("============================================================");

        // 2. 将字符串以空格拆分,最多拆分 2 次(得到 2 个元素的数组)
        String[] srr2 = str.split(" ", 2);
        for (String s : srr2) {
            System.out.println(s);
        }
        System.out.println("============================================================");

        // 3. 特殊分隔符(. | * + , 等)需要使用 \\ 转义才能正常拆分
        String str2 = "name=ZhangSan&age=18";
        String[] srr3 = str2.split("=|&");
        for (String s : srr3) {
            System.out.println(s);
        }
    }
}

字符串截取和去除空格

字符串截取

按指定索引范围截取子字符串,遵循「左闭右开」原则。

去除空格

仅去除字符串两端的空格,中间空格保留。

public class SubStringAndTrim {
    public static void main(String[] args) {
        String str1 = "hello meat";

        // 1. 字符串截取
        // 1.1 从指定索引截取到字符串结尾:str.substring(index)
        System.out.println(str1.substring(5));
        // 1.2 截取指定索引范围内的内容(左闭右开):str.substring(beginIndex, endIndex)
        System.out.println(str1.substring(5, 8));
        System.out.println("============================================================");

        String str2 = "  hello world  ";

        // 2. 去除两边的空格:str.trim()
        System.out.println("原始字符串:" + str2);
        System.out.println("去除两端空格后:" + str2.trim());
    }
}

intern() 方法

intern() 方法用于将堆中的 String 对象入池(字符串常量池),复用常量池中的对象,减少内存占用。

public class StringIntern {
    public static void main(String[] args) {

        char[] ch = new char[]{'a', 'b', 'c'};
        String str1 = new String(ch);

        // 调用此方法后,将 str1 对象的内容放入字符串常量池中(若不存在)
        str1.intern();
        
        // "abc" 已存在于字符串常量池中,str2 直接引用常量池中的对象
        String str2 = "abc";

        // 返回 true,若未调用 intern() 方法则返回 false
        System.out.println(str1 == str2);

    }
}

字符串转换

支持多种数据类型与字符串之间的相互转换,以及字符串的大小写、格式转换。

public class StringTransfer {

    public static void main(String[] args) {

        // 1. 其他数据类型转换为字符串:String.valueOf(...)(推荐,避免空指针异常)
        String s1 = String.valueOf(1); // 整型 -> 字符串
        String s2 = String.valueOf(1.1); // 浮点型 -> 字符串
        String s3 = String.valueOf(true); // 布尔型 -> 字符串
        String s4 = String.valueOf(new Student("LiHua", 18)); // 自定义对象 -> 字符串(依赖 toString() 方法)
        System.out.println(s1 + "   " + s2 + "   " + s3 + "   " + s4);
        System.out.println("============================================================");

        // 2. 字符串转为基本数据类型:封装类.parseXxx("...")
        int a = Integer.parseInt("1"); // 字符串 -> 整型
        double b = Double.parseDouble("1.1"); // 字符串 -> 浮点型
        System.out.println(a);
        System.out.println(b);
        System.out.println("============================================================");

        // 3. 字符串大小写转换
        String str1 = "Hello";
        String str2 = "HELLO";
        System.out.println(str1.toUpperCase()); // 小写 -> 大写
        System.out.println(str2.toLowerCase()); // 大写 -> 小写
        System.out.println("============================================================");

        // 4. 字符串 <-> 字符数组
        // 4.1 字符串转为字符数组:str.toCharArray()
        String str3 = "Hello";
        char[] ch = str3.toCharArray();
        for (char c : ch) {
            System.out.print(c + " ");
        }
        System.out.println();
        System.out.println("============================================================");
        // 4.2 字符数组转为字符串:new String(字符数组)
        String str4 = new String(ch);
        System.out.println(str4);
        System.out.println("============================================================");

        // 5. 字符串格式化输出:String.format("格式字符串", 参数...)
        String str5 = String.format("%d,%d,%d", 2020,1,1);
        System.out.println(str5);
    }
}

重写 toString() 方法

自定义对象转换为字符串时,默认调用 Object 类的 toString() 方法(返回「类名@哈希值」),重写后可返回自定义格式的内容。

class Student {
    String name;
    int age;

    // 构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 重写 toString() 方法
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

二、StringBuffer 和 StringBuilder

由于 String 是不可变字符序列,频繁修改字符串会产生大量临时对象,浪费内存。StringBufferStringBuilder 是可变字符序列,专门用于频繁修改字符串的场景,两者的方法基本一致,核心区别在于线程安全性

核心区别

  1. StringBuffer:线程安全,方法添加了 synchronized 关键字修饰,多线程环境下安全,效率较低。
  2. StringBuilder:非线程安全,无 synchronized 修饰,单线程环境下效率更高(推荐优先使用)。

重要说明

  1. StringBufferStringBuilder 不能与 String 直接转换。
  2. StringStringBuffer/StringBuilder:调用构造方法或 append() 方法。
  3. StringBuffer/StringBuilderString:调用 toString() 方法。
  4. 两者的核心方法(如 append())声明有区别(StringBuffer 多了 synchronized)。
// StringBuilder 的 append() 方法(无同步锁)
public static StringBuilder append(String s) {
    StringBuilder sb = new StringBuilder();
    sb.append(s);
    return sb;
}

// StringBuffer 的 append() 方法(有同步锁 synchronized)
public static synchronized StringBuffer append(String s) {
    StringBuffer sb = new StringBuffer();
    sb.append(s);
    return sb;
}

StringBuilder 常用方法

StringBuffer 的方法使用方式与 StringBuilder 完全一致,此处以 StringBuilder 为例演示核心方法。

public static void main(String[] args) {

    StringBuilder sb1 = new StringBuilder("hello");
    StringBuilder sb2 = sb1;
    
    sb1.append(" "); // 字符串尾插内容
    sb1.append("meat");
    System.out.println(sb1 == sb2); // true(可变对象,修改的是自身内容,引用地址不变)
    System.out.println(sb1.charAt(0)); // 获取指定下标的字符
    System.out.println(sb1.length()); // 获取字符串实际长度
    System.out.println(sb1.capacity()); // 获取底层数组的容量(大于等于实际长度)
    sb1.setCharAt(0, 'H'); // 修改指定下标的字符为'H'
    sb1.insert(0, "Wow"); // 在下标为0的位置插入字符串
    System.out.println(sb1.indexOf("hello")); // 正向查找第一次出现指定字符串的下标
    System.out.println(sb1.lastIndexOf("hello")); // 反向查找第一次出现指定字符串的下标
    sb1.deleteCharAt(0); // 删除指定下标的字符
    sb1.delete(0, 2); // 删除[0, 2)范围内的字符(左闭右开)
    String str1 = sb1.substring(0, 2); // 截取[0, 2)范围内的字符,返回新的String对象
    String str2 = sb1.toString(); // 将StringBuilder转换为String对象
    sb1.reverse(); // 翻转字符串内容
}
Cloneable 2025-07-10
常用工具类 2025-07-19

评论区