杰瑞科技汇

Java字符串用法有哪些关键点?

  1. String 的基本概念与特性
  2. String 的创建与初始化
  3. String 的常用方法详解
  4. String 不可变性的深入理解
  5. StringStringBuilderStringBuffer 的区别与选择
  6. String 的其他高级用法

String 的基本概念与特性

String 在 Java 中代表一个字符序列,也就是我们常说的字符串。

Java字符串用法有哪些关键点?-图1
(图片来源网络,侵删)

核心特性:不可变性

这是 String 最重要、最核心的特性,一旦一个 String 对象被创建,它的内容(即字符序列)就不能被修改

  • 任何对字符串的修改操作(如 replace, substring, concat 等)都不会改变原始的 String 对象。
  • 这些操作实际上会创建并返回一个新的 String 对象,新对象包含了修改后的内容,而原始对象保持不变。

为什么设计成不可变?

  1. 线程安全:不可变对象天生就是线程安全的,因为多个线程无法同时修改它,避免了同步开销。
  2. 安全:在 Java 中,String 被广泛用于表示文件路径、网络地址、数据库 URL 等敏感信息。String 可变,这些信息可能会在程序运行过程中被恶意修改,带来安全隐患。
  3. 性能优化(字符串常量池):由于不可变,JVM 可以对 String 对象进行缓存和重用,这就是字符串常量池的原理,可以大大节省内存。

String 的创建与初始化

创建 String 对象主要有两种方式。

使用字面量

String str1 = "Hello";
String str2 = "Hello"; 

这种方式创建的字符串会被存放在字符串常量池 中,由于 str1str2 的内容相同,JVM 会让它们指向常量池中的同一个对象,str1 == str2 的结果为 true

System.out.println(str1 == str2); // 输出 true

使用 new 关键字

String str3 = new String("Hello");
String str4 = new String("Hello");

这种方式会在堆内存 中创建新的 String 对象,即使内容相同,new 也会创建不同的对象实例。

System.out.println(str3 == str4); // 输出 false
// 因为它们是堆上两个不同的对象

intern() 方法intern() 方法会尝试将字符串对象放入常量池,如果常量池中已存在该字符串,则返回常量池中的引用;否则,将当前字符串加入常量池并返回其引用。

String s1 = new String("Hello");
String s2 = s1.intern(); // s2 现在指向常量池中的 "Hello"
String s3 = "Hello";
System.out.println(s1 == s2); // false, s1在堆上,s2在常量池
System.out.println(s2 == s3); // true, s2和s3都指向常量池中的同一个对象

String 的常用方法详解

以下是 String 类中最常用的一些方法,建议熟练掌握。

1 长度与访问

  • length(): 返回字符串的长度(字符数)。
    String s = "Java";
    System.out.println(s.length()); // 输出 4
  • charAt(int index): 返回指定索引处的字符。
    System.out.println(s.charAt(0)); // 输出 'J'
  • getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin): 将字符串的一部分复制到字符数组中。

2 查找

  • indexOf(char/String): 从字符串开头查找,返回字符或子串第一次出现时的索引,找不到则返回 -1
    String text = "Hello world, hello Java";
    System.out.println(text.indexOf('o')); // 输出 4
    System.out.println(text.indexOf("hello")); // 输出 13
  • lastIndexOf(char/String): 从字符串末尾查找,返回字符或子串最后一次出现时的索引。
    System.out.println(text.lastIndexOf('o')); // 输出 7
  • contains(CharSequence): 判断字符串是否包含指定的字符序列,返回 boolean
    System.out.println(text.contains("Java")); // 输出 true

3 比较

  • equals(Object): 比较两个字符串的是否完全相同,区分大小写。
    String s1 = "hello";
    String s2 = "Hello";
    System.out.println(s1.equals(s2)); // 输出 false
  • equalsIgnoreCase(String): 比较两个字符串的内容是否相同,不区分大小写
    System.out.println(s1.equalsIgnoreCase(s2)); // 输出 true
  • compareTo(String): 字典序比较,如果两个字符串相等,返回 0;如果小于参数字符串,返回负数;否则返回正数。
    String a = "apple";
    String b = "banana";
    System.out.println(a.compareTo(b)); // 输出负数
  • startsWith(String) / endsWith(String): 判断字符串是否以指定的前缀/后缀开头或结尾。
    System.out.println(text.startsWith("Hello")); // 输出 true
    System.out.println(text.endsWith("Java"));   // 输出 true

4 修改与创建新字符串(注意:原字符串不变)

  • substring(int beginIndex): 返回从 beginIndex 开始到末尾的子串。
  • substring(int beginIndex, int endIndex): 返回从 beginIndex 开始到 endIndex(不包括)的子串。
    String path = "/usr/local/bin";
    System.out.println(path.substring(5));      // 输出 local/bin
    System.out.println(path.substring(5, 10)); // 输出 local
  • concat(String): 连接两个字符串。
    String s = "Java";
    String newS = s.concat(" is awesome!");
    System.out.println(newS); // 输出 Java is awesome!
    System.out.println(s);    // 输出 Java (原字符串未变)
  • replace(char oldChar, char newChar) / replace(CharSequence target, CharSequence replacement): 替换字符或子串。
    String msg = "Hello World";
    String newMsg = msg.replace('l', 'r'); // Herra Worrd
    System.out.println(newMsg);
  • toLowerCase() / toUpperCase(): 转换为小写/大写。
    System.out.println("Java".toLowerCase()); // 输出 java
  • trim(): 去除字符串两端的空白字符(空格、制表符、换行等)。
    System.out.println("  Java  ".trim()); // 输出 "Java"

5 分割与连接

  • split(String regex): 根据给定的正则表达式分割字符串,返回一个字符串数组。
    String csv = "apple,banana,orange";
    String[] fruits = csv.split(",");
    // fruits 数组为 ["apple", "banana", "orange"]
  • join(CharSequence delimiter, CharSequence... elements): (Java 8+) 将多个字符串用指定的分隔符连接起来。
    String result = String.join("-", "2025", "10", "27");
    System.out.println(result); // 输出 2025-10-27

6 格式化

  • format(String format, Object... args): 格式化字符串,类似于 C 语言的 printf
    String name = "Alice";
    int age = 30;
    String formatted = String.format("My name is %s and I am %d years old.", name, age);
    System.out.println(formatted); // 输出 My name is Alice and I am 30 years old.

String 不可变性的深入理解

让我们通过代码来直观感受不可变性:

String s = "original";
System.out.println("Original s: " + s); // original
// 调用 toUpperCase() 方法
s = s.toUpperCase(); 
// 注意:这里不是修改了 s 对象,而是创建了一个新的对象 "ORIGINAL"
// 然后让引用 s 指向了这个新对象
System.out.println("After modification: " + s); // ORIGINAL

内存示意图

  1. String s = "original";

    s  ----->  "original" (在常量池)
  2. s = s.toUpperCase();

    • s.toUpperCase() 创建了一个新的字符串对象 "ORIGINAL"
    • 引用 s 不再指向 "original",而是指向了新的 "ORIGINAL"
    • "original" 对象如果没有其他引用,会被垃圾回收器回收。
    s  ----->  "ORIGINAL" (在常量池)
    "original" (可能被回收)

StringStringBuilderStringBuffer 的区别与选择

特性 String StringBuilder StringBuffer
可变性 不可变 可变 可变
线程安全 线程安全 非线程安全 线程安全
性能 - (频繁修改性能差) (无同步开销) 较低 (有同步开销)
主要用途 存储不变的文本信息 单线程环境下进行大量字符串拼接、修改 多线程环境下进行大量字符串拼接、修改

如何选择?

  1. 如果字符串内容不需要改变:直接使用 String

    String userName = "john_doe";
  2. 在单线程环境下,需要频繁修改字符串内容(如循环拼接):使用 StringBuilder,性能最好。

    // 错误示范:在循环中拼接字符串,效率极低
    String result = "";
    for (int i = 0; i < 1000; i++) {
        result += "a"; // 每次循环都创建新对象
    }
    // 正确示范
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
        sb.append("a"); // 在原对象上修改,效率高
    }
    String finalResult = sb.toString();
  3. 在多线程环境下,需要安全地修改字符串内容:使用 StringBuffer

    • StringBuffer 的方法大多被 synchronized 修饰,保证了线程安全,但因此牺牲了一部分性能。
    • 在现代 Java 开发中,如果对性能要求极高且确实需要线程安全的字符串操作,有时会考虑使用外部锁来同步 StringBuilder,但绝大多数情况下,StringBuffer 已经足够。

String 的其他高级用法

  • 正则表达式String 类提供了 matches(), replaceAll(), split() 等方法支持正则表达式,非常强大。

    String email = "test.user+123@example.com";
    // 移除所有非字母数字的字符
    String cleaned = email.replaceAll("[^a-zA-Z0-9]", ""); 
    System.out.println(cleaned); // testuser123examplecom
  • String 与基本数据类型转换

    • String -> int: Integer.parseInt("123")
    • String -> double: Double.parseDouble("12.34")
    • int -> String: String.valueOf(123)123 + ""
    • double -> String: String.valueOf(12.34)
  • String 与字符数组转换

    • String -> char[]: toCharArray()
    • char[] -> String: new String(charArray)String.valueOf(charArray)
  • String 是 Java 中不可变的字符序列。
  • 创建方式有两种:字面量(存于常量池)和 new(存于堆)。
  • 所有修改操作都会返回新对象,原对象不变,这是初学者最容易混淆的地方。
  • 对于少量、静态的字符串,使用 String
  • 对于大量、动态的字符串拼接或修改,在单线程用 StringBuilder,多线程用 StringBuffer

熟练掌握 String 的用法是编写高质量 Java 代码的基础,希望这份详细的指南能帮助你!

分享:
扫描分享到社交APP
上一篇
下一篇