欢迎光临
我们一直在努力

Java字符串全解:从String到StringTokenizer,期末复习与实战指南

9.1 字符串概述

在Java编程中,字符串(String)是使用最频繁的数据类型之一,它代表一个不可变的字符序列。本章将系统性地梳理Java字符串相关的核心类:String、StringBuilder、StringBuffer以及一个较老的字符串分割工具StringTokenizer。理解它们的特性和适用场景,不仅是期末考试的重要考点,更是日后项目开发的实操基础。

学习目标:

  • 掌握String的创建、不可变性及其影响。
  • 理解StringBuilder和StringBuffer的可变性及适用场景。
  • 学会使用StringTokenizer进行字符串分割。
  • 能够根据实际需求(如性能、线程安全)选择合适的字符串类。

9.2 String(创建+使用)

String类是java.lang包下的核心类,用于创建和操作不可变的字符串。

9.2.1 创建String对象的两种方式

创建String对象主要有两种方式:直接赋值和使用new关键字。

1. 直接赋值

String s1 = "Hello";
String s2 = "Hello";

运行输出分析:
s1 == s2 的结果为 true。这是因为字符串字面量"Hello"被存储在字符串常量池中。s1和s2指向的是常量池中的同一个对象,所以引用地址相同。

2. 使用new关键字

String s3 = new String("Hello");
String s4 = new String("Hello");

运行输出分析:
s3 == s4 的结果为 false。new关键字会在堆内存中创建一个新的String对象,即使内容相同,s3和s4也是两个不同的对象,引用地址不同。
s3.equals(s4) 的结果为 true,因为equals方法比较的是字符串的内容。

9.2.2 String类的常用方法

String提供了丰富的方法来操作字符串,以下是一些核心方法及其测试代码:

public class StringDemo {
public static void main(String[] args) {
String str = " Java Programming ";

// 1. 获取长度
System.out.println("长度: " + str.length()); // 输出: 长度: 20

// 2. 去除首尾空格
String trimmed = str.trim();
System.out.println("去除空格后: \\"" + trimmed + "\\""); // 输出: 去除空格后: "Java Programming"

// 3. 获取子字符串
String sub = str.substring(5, 16); // 索引从0开始,[5,16)
System.out.println("子串: " + sub); // 输出: 子串: Programming

// 4. 查找字符/字符串位置
int index = str.indexOf("Pro");
System.out.println("\\"Pro\\"的索引: " + index); // 输出: "Pro"的索引: 7

// 5. 字符串替换
String replaced = str.replace("Java", "Python");
System.out.println("替换后: " + replaced); // 输出: 替换后: Python Programming

// 6. 大小写转换
System.out.println("大写: " + str.toUpperCase()); // 输出: 大写: JAVA PROGRAMMING
System.out.println("小写: " + str.toLowerCase()); // 输出: 小写: java programming

// 7. 分割字符串
String csv = "Apple,Banana,Orange";
String[] fruits = csv.split(",");
System.out.println("分割后第一个水果: " + fruits[0]); // 输出: 分割后第一个水果: Apple
}
}

考点提示:牢记substring是前闭后开区间 [beginIndex, endIndex),indexOf找不到返回-1。

9.3 StringBuilder(创建+使用)

StringBuilder代表一个可变的字符序列。当需要频繁修改字符串内容(如拼接、插入、删除)时,使用StringBuilder比String性能高得多,因为它避免了创建大量临时String对象。

9.3.1 创建与基本使用

public class StringBuilderDemo {
public static void main(String[] args) {
// 1. 创建
StringBuilder sb1 = new StringBuilder(); // 默认容量16
StringBuilder sb2 = new StringBuilder("Hello"); // 指定初始内容
StringBuilder sb3 = new StringBuilder(50); // 指定初始容量

// 2. 追加内容
sb1.append("Java");
sb1.append(" ");
sb1.append(17); // 可以追加任何类型,自动转为字符串
System.out.println("追加后: " + sb1.toString()); // 输出: 追加后: Java 17

// 3. 插入内容
sb2.insert(5, " World");
System.out.println("插入后: " + sb2); // 输出: 插入后: Hello World

// 4. 删除内容
sb2.delete(5, 11); // 删除[5,11)位置的字符
System.out.println("删除后: " + sb2); // 输出: 删除后: Hello

// 5. 替换内容
sb2.replace(0, 5, "Hi");
System.out.println("替换后: " + sb2); // 输出: 替换后: Hi

// 6. 反转字符串
sb2.reverse();
System.out.println("反转后: " + sb2); // 输出: 反转后: iH
}
}

实操重点:在单线程环境下进行大量字符串修改操作,StringBuilder是首选。

9.4 StringBuffer

StringBuffer与StringBuilder在功能上几乎完全相同,都代表可变的字符序列。它们的关键区别在于线程安全性。

9.4.1 核心特性与使用

StringBuffer的方法是同步的(synchronized),因此是线程安全的。这意味着多个线程可以安全地同时操作同一个StringBuffer对象。而StringBuilder的方法是非同步的,线程不安全,但在单线程环境下性能更高。

public class StringBufferDemo {
public static void main(String[] args) {
StringBuffer sbf = new StringBuffer("ThreadSafe");

// 方法与StringBuilder类似
sbf.append(" Buffer");
System.out.println(sbf); // 输出: ThreadSafe Buffer

sbf.insert(10, "-");
System.out.println(sbf); // 输出: ThreadSafe- Buffer
}
}

考点与选择策略:

  • 考点:StringBuffer vs StringBuilder 的核心区别是线程安全性。
  • 实操:绝大多数现代应用都是单线程操作字符串,因此优先使用StringBuilder。只有在明确涉及多线程共享并修改同一个字符串对象时,才考虑使用StringBuffer。

9.5 StringTokenizer

StringTokenizer是一个用于分割字符串的遗留类(Legacy Class),位于java.util包。虽然现在更推荐使用String的split()方法或正则表达式,但理解它仍有必要,尤其是在处理一些简单分隔符或考试中。

9.5.1 基本用法

import java.util.StringTokenizer;

public class StringTokenizerDemo {
public static void main(String[] args) {
String data = "Java,Python,JavaScript,C++";

// 默认分隔符为空格、制表符、换行符等
// 此处指定逗号为分隔符
StringTokenizer st = new StringTokenizer(data, ",");

System.out.println("令牌数量: " + st.countTokens()); // 输出: 令牌数量: 4

// 遍历所有令牌
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
// 输出:
// Java
// Python
// JavaScript
// C++
}
}

9.5.2 StringTokenizer vs String.split()

特性StringTokenizerString.split() (基于正则表达式)
所属包 java.util (遗留类) java.lang.String
功能 仅按分隔符拆分 按正则表达式拆分,功能强大
空令牌处理 默认忽略空字符串 默认保留空字符串(除非使用限定符)
性能 对于简单分隔符,性能稍好 正则表达式编译有开销,但功能更灵活
推荐度 不推荐在新代码中使用 推荐使用,功能全面,API现代

实操建议:除非在处理性能极其敏感且分隔规则极其简单的场景,否则一律使用String.split()或java.util.regex.Pattern。

对比与总结

对比表格1:String直接赋值 vs new String()

对比项直接赋值 (String s = “abc”)new String(“abc”)
内存区域 字符串常量池 堆内存
对象数量 常量池中只有一个对象,所有相同字面量共享 每次new都会在堆中创建一个新对象
==比较 相同字面量比较为true 即使内容相同,比较也为false
适用场景 推荐,节省内存 需要明确创建独立对象时

对比表格2:三大字符串类核心差异

特性StringStringBuilderStringBuffer
可变性 不可变 (Immutable) 可变 (Mutable) 可变 (Mutable)
线程安全 是(因为不可变) 是 (方法同步)
性能 修改性能差(创建新对象) 高 (单线程) 较低(因同步开销)
使用场景 存储不变字符串、作为键 单线程下频繁修改字符串 多线程下共享修改字符串
诞生版本 Java 1.0 Java 5 Java 1.0

易错考点整理

1. 常量池陷阱

String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = s3.intern(); // 将s3指向的对象放入常量池,并返回常量池引用

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true (intern后)

考点:理解==比较引用,equals比较内容。intern()方法可以主动将字符串对象放入常量池。

2. 循环拼接性能问题

错误示范(性能极差):

String result = "";
for (int i = 0; i < 10000; i++) {
result += i; // 每次循环都创建新的String对象和StringBuilder对象!
}

正确做法(使用StringBuilder):

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
sb.append(i);
}
String result = sb.toString();

3. 线程安全问题

  • String:线程安全(不可变)。
  • StringBuilder:非线程安全。多线程操作同一对象需自行加锁。
  • StringBuffer:线程安全(内部同步),但性能有损耗。

复习思考题

  • 基础概念:String类的不可变性指的是什么?这种设计带来了哪些优点和缺点?
  • 代码分析:以下代码会创建几个String对象?String s1 = "abc";
    String s2 = new String("abc");
    String s3 = s2.intern();

  • 性能选择:在一个单线程的Web服务器中,需要动态生成一个很长的HTML字符串,应该选择String、StringBuilder还是StringBuffer?为什么?
  • 方法辨析:String的split()方法和StringTokenizer在分割字符串“a,b,c”(以逗号分隔)时,输出结果有何不同?
  • 实战应用:如何判断一个字符串是否为回文字符串(正读反读都一样)?请用StringBuilder或StringBuffer实现。

  • 本文涵盖了Java字符串章节的核心知识点、代码示例与易错点,适合作为期末复习笔记。建议读者亲手运行所有示例代码,并结合思考题进行巩固,祝大家考试顺利!

    赞(0)
    未经允许不得转载:171主机测评 » Java字符串全解:从String到StringTokenizer,期末复习与实战指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址