第6章 Java标准类库
6.1 简介
Java标准类库(Java Standard Library)是JDK自带的一套丰富的API集合,包含了数千个预定义的类和方法,用于处理字符串、数学计算、日期时间、集合操作等各种常见任务。这些类库组织在java.lang、java.util、java.time等包中,无需额外安装即可使用。
核心特点:
- 开箱即用:JDK安装后即可使用
- 跨平台:在所有支持Java的平台上行为一致
- 高性能:经过多年优化,性能可靠
- 向后兼容:新版本保持对旧API的兼容
6.2 字符串类
6.2.1 String类
概念介绍:
String类表示不可变的字符序列,是Java中最常用的类之一。String对象一旦创建,其内容就不能被修改。
核心常用API方法:
length():返回字符串长度charAt(int index):返回指定索引处的字符substring(int beginIndex, int endIndex):截取子字符串indexOf(String str):查找子字符串位置equals(Object obj):比较字符串内容toUpperCase()/toLowerCase():大小写转换trim():去除首尾空格split(String regex):按正则表达式分割字符串
完整可运行代码示例:
public class StringExample {
public static void main(String[] args) {
// 1. 创建字符串
String str1 = "Hello, Java!";
String str2 = new String("Hello, World!");
// 2. 基本操作
System.out.println("字符串长度: " + str1.length()); // 12
System.out.println("第7个字符: " + str1.charAt(6)); // J
System.out.println("子字符串: " + str1.substring(7, 11)); // Java
// 3. 查找与比较
System.out.println("包含Java吗? " + str1.contains("Java")); // true
System.out.println("Java的位置: " + str1.indexOf("Java")); // 7
System.out.println("字符串相等吗? " + str1.equals(str2)); // false
// 4. 转换操作
System.out.println("大写: " + str1.toUpperCase()); // HELLO, JAVA!
System.out.println("小写: " + str1.toLowerCase()); // hello, java!
// 5. 分割字符串
String csv = "苹果,香蕉,橙子,葡萄";
String[] fruits = csv.split(",");
System.out.println("水果列表:");
for (String fruit : fruits) {
System.out.println(" - " + fruit);
}
}
}
运行结果:
字符串长度: 12
第7个字符: J
子字符串: Java
包含Java吗? true
Java的位置: 7
字符串相等吗? false
大写: HELLO, JAVA!
小写: hello, java!
水果列表:
- 苹果
- 香蕉
- 橙子
- 葡萄
使用场景与易错点:
- 适用场景:文本处理、用户输入验证、配置文件读取、日志输出等
- 易错点1:使用
==比较字符串内容(应使用equals()方法) - 易错点2:在循环中频繁拼接字符串(应使用StringBuilder)
- 易错点3:忽略字符串不可变性,误以为修改了原字符串
6.2.2 StringBuffer类
概念介绍:
StringBuffer类表示可变的字符序列,可以在原对象上修改内容,适用于需要频繁修改字符串的场景。
核心常用API方法:
append(String str):追加字符串insert(int offset, String str):在指定位置插入delete(int start, int end):删除指定范围的字符reverse():反转字符串toString():转换为String对象
完整可运行代码示例:
public class StringBufferExample {
public static void main(String[] args) {
// 创建StringBuffer对象
StringBuffer sb = new StringBuffer("Hello");
// 追加操作
sb.append(" World");
System.out.println("追加后: " + sb); // Hello World
// 插入操作
sb.insert(5, ",");
System.out.println("插入后: " + sb); // Hello, World
// 删除操作
sb.delete(5, 6);
System.out.println("删除后: " + sb); // Hello World
// 替换操作
sb.replace(6, 11, "Java");
System.out.println("替换后: " + sb); // Hello Java
// 反转操作
sb.reverse();
System.out.println("反转后: " + sb); // avaJ olleH
// 转换回String
String result = sb.toString();
System.out.println("最终字符串: " + result);
}
}
运行结果:
追加后: Hello World
插入后: Hello, World
删除后: Hello World
替换后: Hello Java
反转后: avaJ olleH
最终字符串: avaJ olleH
String vs StringBuffer对比:
| 特性 | String | StringBuffer |
|---|---|---|
| 可变性 | 不可变 | 可变 |
| 线程安全 | 线程安全 | 线程安全 |
| 性能 | 拼接性能差 | 拼接性能好 |
| 内存 | 每次修改创建新对象 | 在原对象上修改 |
| 适用场景 | 不频繁修改的字符串 | 频繁修改的字符串 |
使用场景与易错点:
- 适用场景:大量字符串拼接、动态构建SQL语句、处理用户输入流
- 易错点1:在单线程环境下使用StringBuffer(应使用StringBuilder)
- 易错点2:忘记调用
toString()方法转换 - 易错点3:在多线程环境下使用StringBuilder(应使用StringBuffer)
6.2.3 正则表达式
概念介绍:
正则表达式(Regular Expression)是一种用于匹配字符串模式的强大工具,Java通过java.util.regex包提供支持。
核心常用API方法:
Pattern.compile(String regex):编译正则表达式Matcher.matches():尝试匹配整个字符串Matcher.find():查找下一个匹配项Matcher.group():返回匹配的字符串String.matches(String regex):快速匹配方法
常用正则表达式模式:
\d:数字\w:单词字符(字母、数字、下划线)\s:空白字符[abc]:a、b或c中的任意一个[^abc]:除了a、b、c的任意字符a{3}:恰好3个aa{3,}:至少3个aa{3,5}:3到5个a
完整可运行代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexExample {
public static void main(String[] args) {
System.out.println("=== 1. 验证邮箱格式 ===");
// 定义邮箱正则表达式
String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
Pattern emailPattern = Pattern.compile(emailRegex);
// 测试邮箱地址
String[] emails = {
"user@example.com", // 有效
"john.doe123@gmail.com", // 有效
"admin@company.co.uk", // 有效
"invalid-email", // 无效:缺少@和域名
"user@.com", // 无效:@后直接点
"@example.com", // 无效:缺少用户名
"user@com", // 无效:域名太短
"user@example.c" // 无效:顶级域名太短
};
System.out.println("邮箱验证结果:");
for (String email : emails) {
Matcher matcher = emailPattern.matcher(email);
boolean isValid = matcher.matches();
System.out.printf(" %-25s -> %s%n", email, isValid ? "有效" : "无效");
}
System.out.println("\n=== 2. 提取电话号码 ===");
// 定义电话号码正则表达式(支持多种格式)
String phoneRegex = "\\b(\\+?86)?[1][3-9]\\d{9}\\b|\\b0\\d{2,3}-?\\d{7,8}\\b";
Pattern phonePattern = Pattern.compile(phoneRegex);
// 测试文本
String text = "联系方式:张三 13812345678,李四 +8613912345678," +
"公司电话:010-12345678,客服:400-888-9999," +
"无效号码:12345,手机:12-34567890";
System.out.println("原文:" + text);
System.out.println("\n提取到的电话号码:");
Matcher phoneMatcher = phonePattern.matcher(text);
int count = 0;
while (phoneMatcher.find()) {
count++;
System.out.println(" " + count + ". " + phoneMatcher.group());
}
System.out.println("共找到 " + count + " 个有效电话号码");
System.out.println("\n=== 3. Pattern和Matcher高级用法 ===");
// 复杂文本提取示例
String logText = "2023-10-25 10:30:15 [INFO] User login: user123 from IP 192.168.1.100\n" +
"2023-10-25 10:35:22 [ERROR] Database connection failed: timeout after 5000ms\n" +
"2023-10-25 10:40:10 [WARN] Memory usage high: 85%";
// 提取日志中的时间、级别、消息
String logRegex = "(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[([A-Z]+)\\] (.+)";
Pattern logPattern = Pattern.compile(logRegex);
Matcher logMatcher = logPattern.matcher(logText);
System.out.println("日志解析结果:");
while (logMatcher.find()) {
String timestamp = logMatcher.group(1);
String level = logMatcher.group(2);
String message = logMatcher.group(3);
System.out.printf(" 时间: %s | 级别: %-5s | 消息: %s%n",
timestamp, level, message);
}
System.out.println("\n=== 4. 分组和替换 ===");
// 分组捕获和替换
String dateText = "今天是2023-10-25,明天是2023-10-26";
String dateRegex = "(\\d{4})-(\\d{2})-(\\d{2})";
Pattern datePattern = Pattern.compile(dateRegex);
Matcher dateMatcher = datePattern.matcher(dateText);
// 将yyyy-mm-dd格式替换为dd/mm/yyyy格式
String replacedText = dateMatcher.replaceAll("$3/$2/$1");
System.out.println("原文本: " + dateText);
System.out.println("替换后: " + replacedText);
// 使用String的matches方法快速验证
System.out.println("\n=== 5. 快速验证(String.matches())===");
String quickTest = "Hello123";
boolean isAlphanumeric = quickTest.matches("[a-zA-Z0-9]+");
System.out.println("字符串 \"" + quickTest + "\" 是否只包含字母数字: " + isAlphanumeric);
}
}
运行结果:
=== 1. 验证邮箱格式 ===
邮箱验证结果:
user@example.com -> 有效
john.doe123@gmail.com -> 有效
admin@company.co.uk -> 有效
invalid-email -> 无效
user@.com -> 无效
@example.com -> 无效
user@com -> 无效
user@example.c -> 无效
=== 2. 提取电话号码 ===
原文:联系方式:张三 13812345678,李四 +8613912345678,公司电话:010-12345678,客服:400-888-9999,无效号码:12345,手机:12-34567890
提取到的电话号码:
1. 13812345678
2. +8613912345678
3. 010-12345678
4. 400-888-9999
共找到 4 个有效电话号码
=== 3. Pattern和Matcher高级用法 ===
日志解析结果:
时间: 2023-10-25 10:30:15 | 级别: INFO | 消息: User login: user123 from IP 192.168.1.100
时间: 2023-10-25 10:35:22 | 级别: ERROR | 消息: Database connection failed: timeout after 5000ms
时间: 2023-10-25 10:40:10 | 级别: WARN | 消息: Memory usage high: 85%
=== 4. 分组和替换 ===
原文本: 今天是2023-10-25,明天是2023-10-26
替换后: 今天是25/10/2023,明天是26/10/2023
=== 5. 快速验证(String.matches()) ===
字符串 "Hello123" 是否只包含字母数字: true
使用场景与易错点:
- 适用场景:表单验证、日志分析、数据清洗、文本提取、URL路由匹配
- 易错点1:正则表达式中的特殊字符需要转义(如
.、\、[、]等) - 易错点2:贪婪匹配 vs 非贪婪匹配(
.*vs.*?) - 易错点3:性能问题 - 避免在循环中重复编译Pattern对象
- 易错点4:忘记处理边界情况(如空字符串、null值)
- 最佳实践:复杂正则表达式添加注释,使用
Pattern.COMMENTS标志提高可读性
6.2.4 实用案例6.1:使用正则表达式检查IP地址
完整可运行代码示例:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class IPAddressValidator {
public static void main(String[] args) {
// 定义IP地址的正则表达式
// 解释:每个部分为0-255,用点分隔
String ipPattern = "^((25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)\\.){3}" +
"(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)$";
// 测试用例
String[] testIPs = {
"192.168.1.1", // 有效
"255.255.255.255", // 有效
"0.0.0.0", // 有效
"256.100.100.100", // 无效:256>255
"192.168.1", // 无效:只有3部分
"192.168.1.1.1", // 无效:有5部分
"abc.def.ghi.jkl", // 无效:包含字母
"192.168.01.001" // 无效:前导0(实际中可能允许,这里严格限制)
};
Pattern pattern = Pattern.compile(ipPattern);
System.out.println("IP地址验证结果:");
System.out.println("========================");
for (String ip : testIPs) {
Matcher matcher = pattern.matcher(ip);
boolean isValid = matcher.matches();
System.out.printf("%-20s -> %s%n", ip, isValid ? "有效" : "无效");
}
// 额外示例:提取IP地址
String text = "服务器1: 192.168.1.100, 服务器2: 10.0.0.1, 无效: 999.888.777.666";
System.out.println("\n从文本中提取IP地址:");
System.out.println("原文:" + text);
// 简化的IP模式(用于提取)
String extractPattern = "\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b";
Pattern extractor = Pattern.compile(extractPattern);
Matcher extractMatcher = extractor.matcher(text);
System.out.print("提取结果:");
while (extractMatcher.find()) {
System.out.print(extractMatcher.group() + " ");
}
}
}
运行结果:
IP地址验证结果:
========================
192.168.1.1 -> 有效
255.255.255.255 -> 有效
0.0.0.0 -> 有效
256.100.100.100 -> 无效
192.168.1 -> 无效
192.168.1.1.1 -> 无效
abc.def.ghi.jkl -> 无效
192.168.01.001 -> 无效
从文本中提取IP地址:
原文:服务器1: 192.168.1.100, 服务器2: 10.0.0.1, 无效: 999.888.777.666
提取结果:192.168.1.100 10.0.0.1 999.888.777.666
使用场景与易错点:
- 适用场景:表单验证、日志分析、数据清洗、文本提取
- 易错点1:正则表达式过于复杂难以维护
- 易错点2:忘记转义特殊字符(如
.、\等) - 易错点3:性能问题(避免在循环中重复编译Pattern)
6.3 数据类型包装器类
6.3.1 整型包装器类
概念介绍:
包装器类(Wrapper Classes)将基本数据类型封装成对象,使基本类型具有对象的特性。Java为8种基本类型提供了对应的包装器类。
基本类型与包装器类对应关系:
| 基本类型 | 包装器类 | 字节数 | 取值范围 |
|---|---|---|---|
| byte | Byte | 1 | -128 ~ 127 |
| short | Short | 2 | -32768 ~ 32767 |
| int | Integer | 4 | -2³¹ ~ 2³¹-1 |
| long | Long | 8 | -2⁶³ ~ 2⁶³-1 |
| float | Float | 4 | 单精度浮点数 |
| double | Double | 8 | 双精度浮点数 |
| char | Character | 2 | Unicode字符 |
| boolean | Boolean | 1 | true/false |
核心常用API方法:
valueOf():将基本类型或字符串转换为包装器对象parseXxx():将字符串转换为基本类型xxxValue():获取包装器对象的基本类型值compareTo():比较两个包装器对象toString():转换为字符串
6.3.2 实用案例6.2:字符串和数字的相互转换
完整可运行代码示例:
public class StringNumberConversion {
public static void main(String[] args) {
System.out.println("=== 字符串转数字 ===");
// 1. 字符串转int
String strNum1 = "123";
int num1 = Integer.parseInt(strNum1);
System.out.println("字符串\"" + strNum1 + "\"转int: " + num1);
// 2. 字符串转Integer对象
Integer integerObj = Integer.valueOf(strNum1);
System.out.println("字符串转Integer对象: " + integerObj);
// 3. 处理进制转换
String binaryStr = "1010"; // 二进制
int decimalFromBinary = Integer.parseInt(binaryStr, 2);
System.out.println("二进制\"" + binaryStr + "\"转十进制: " + decimalFromBinary);
String hexStr = "FF"; // 十六进制
int decimalFromHex = Integer.parseInt(hexStr, 16);
System.out.println("十六进制\"" + hexStr + "\"转十进制: " + decimalFromHex);
// 4. 处理异常情况
try {
String invalidStr = "123abc";
int invalidNum = Integer.parseInt(invalidStr);
System.out.println("转换结果: " + invalidNum);
} catch (NumberFormatException e) {
System.out.println("错误:\"" + invalidStr + "\"不是有效的整数");
}
System.out.println("\n=== 数字转字符串 ===");
// 5. int转字符串(多种方式)
int num2 = 456;
// 方式1:使用Integer.toString()
String str1 = Integer.toString(num2);
System.out.println("Integer.toString(): " + str1);
// 方式2:使用String.valueOf()
String str2 = String.valueOf(num2);
System.out.println("String.valueOf(): " + str2);
// 方式3:使用字符串拼接(隐式转换)
String str3 = "" + num2;
System.out.println("字符串拼接: " + str3);
// 方式4:格式化转换
String str4 = String.format("%d", num2);
System.out.println("String.format(): " + str4);
// 6. 进制转换
int num3 = 255;
System.out.println("\n数字" + num3 + "的不同进制表示:");
System.out.println("二进制: " + Integer.toBinaryString(num3));
System.out.println("八进制: " + Integer.toOctalString(num3));
System.out.println("十六进制: " + Integer.toHexString(num3));
System.out.println("\n=== 其他类型转换示例 ===");
// 7. double转换
String doubleStr = "3.14159";
double pi = Double.parseDouble(doubleStr);
System.out.println("字符串转double: " + pi);
System.out.println("double转字符串: " + Double.toString(pi));
// 8. boolean转换
String boolStr = "true";
boolean flag = Boolean.parseBoolean(boolStr);
System.out.println("字符串转boolean: " + flag);
System.out.println("注意:Boolean.parseBoolean()不区分大小写,'True'、'TRUE'都有效");
// 9. 自动装箱与拆箱
System.out.println("\n=== 自动装箱与拆箱 ===");
Integer autoBoxed = 100; // 自动装箱:int -> Integer
int autoUnboxed = autoBoxed; // 自动拆箱:Integer -> int
System.out.println("自动装箱: " + autoBoxed);
System.out.println("自动拆箱: " + autoUnboxed);
// 10. 比较注意事项
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println("\n=== 包装器对象比较注意事项 ===");
System.out.println("a == b (127): " + (a == b)); // true,缓存范围内
System.out.println("c == d (128): " + (c == d)); // false,超出缓存范围
System.out.println("c.equals(d): " + c.equals(d)); // true,值相等
System.out.println("建议:比较包装器对象时使用equals()方法");
}
}
运行结果:
=== 字符串转数字 ===
字符串"123"转int: 123
字符串转Integer对象: 123
二进制"1010"转十进制: 10
十六进制"FF"转十进制: 255
错误:"123abc"不是有效的整数
=== 数字转字符串 ===
Integer.toString(): 456
String.valueOf(): 456
字符串拼接: 456
String.format(): 456
数字255的不同进制表示:
二进制: 11111111
八进制: 377
十六进制: ff
=== 其他类型转换示例 ===
字符串转double: 3.14159
double转字符串: 3.14159
字符串转boolean: true
注意:Boolean.parseBoolean()不区分大小写,'True'、'TRUE'都有效
## 6.4 本章总结与练习
### 本章核心要点总结
#### 1. 字符串类(String & StringBuffer)
- **String类**:不可变字符序列,适用于不频繁修改的字符串操作
- 常用方法:`length()`、`charAt()`、`substring()`、`indexOf()`、`equals()`、`split()`等
- 易错点:使用`==`比较内容、循环中频繁拼接、忽略不可变性
- **StringBuffer类**:可变字符序列,线程安全,适用于频繁修改的字符串
- 常用方法:`append()`、`insert()`、`delete()`、`reverse()`、`toString()`
- 与StringBuilder区别:StringBuffer线程安全,StringBuilder非线程安全但性能更好
- **正则表达式**:强大的字符串模式匹配工具
- 核心类:`Pattern`(编译正则)、`Matcher`(执行匹配)
- 常用方法:`matches()`、`find()`、`group()`、`replaceAll()`
- 易错点:特殊字符转义、贪婪/非贪婪匹配、性能优化
#### 2. 数据类型包装器类
- **包装器类作用**:将基本数据类型封装为对象,实现面向对象操作
- **8种基本类型对应包装器**:Byte、Short、Integer、Long、Float、Double、Character、Boolean
- **核心转换方法**:
- 字符串转基本类型:`parseXxx()`(如`Integer.parseInt()`)
- 字符串转包装器对象:`valueOf()`(如`Integer.valueOf()`)
- 基本类型转字符串:`toString()`、`String.valueOf()`、字符串拼接
- **自动装箱与拆箱**:Java自动在基本类型和包装器类型间转换
- **比较注意事项**:包装器对象比较应使用`equals()`而非`==`(缓存范围外)
#### 3. 核心编程思想
- **不可变对象优势**:线程安全、缓存友好、适合作为Map键
- **可变对象适用场景**:频繁修改、性能敏感的操作
- **异常处理**:转换失败时正确处理`NumberFormatException`
- **性能优化**:避免在循环中重复创建对象、编译正则表达式
### 编程练习题
#### 练习题1:统计字符串中每个字符出现的次数
**题目要求:**
编写一个方法`countCharacters(String str)`,统计给定字符串中每个字符出现的次数(区分大小写),并返回一个Map<Character, Integer>。
**示例输入输出:**
输入: “Hello World”
输出: {H=1, e=1, l=3, o=2, =1, W=1, r=1, d=1}
**参考实现:**
```java
import java.util.HashMap;
import java.util.Map;
public class CharacterCounter {
public static Map<Character, Integer> countCharacters(String str) {
Map<Character, Integer> charCount = new HashMap<>();
// 遍历字符串中的每个字符
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
// 如果字符已存在,计数加1;否则初始化为1
if (charCount.containsKey(ch)) {
charCount.put(ch, charCount.get(ch) + 1);
} else {
charCount.put(ch, 1);
}
}
return charCount;
}
public static void main(String[] args) {
String testStr = "Hello World";
Map<Character, Integer> result = countCharacters(testStr);
System.out.println("字符串: \"" + testStr + "\"");
System.out.println("字符统计结果:");
for (Map.Entry<Character, Integer> entry : result.entrySet()) {
char ch = entry.getKey();
int count = entry.getValue();
System.out.printf(" '%c' : %d次%n", ch, count);
}
}
}
运行结果:
字符串: "Hello World"
字符统计结果:
'H' : 1次
'e' : 1次
'l' : 3次
'o' : 2次
' ' : 1次
'W' : 1次
'r' : 1次
'd' : 1次
扩展挑战:
- 修改方法,使其不区分大小写(将字符统一转为小写)
- 只统计字母字符,忽略空格和标点符号
- 按字符出现次数降序排序输出
练习题3:字符串处理综合应用
题目要求:
编写一个程序,实现以下功能:
- 从用户输入读取一段文本
- 统计文本中的单词数量(以空格分隔)
- 找出出现频率最高的3个单词
- 将所有数字替换为"[NUMBER]"
- 将处理后的文本保存到文件
提示:
- 使用
Scanner类读取用户输入 - 使用
String.split()方法分割单词 - 使用
Map<String, Integer>统计词频 - 使用正则表达式
\\d+匹配数字 - 使用
FileWriter或BufferedWriter写入文件
学习建议
- 动手实践:亲自编写并运行所有示例代码,理解每个API的用法
- 调试技巧:使用IDE的调试功能,观察字符串和包装器对象在内存中的变化
- 性能测试:对比String、StringBuffer、StringBuilder在不同场景下的性能差异
- 扩展学习:查阅Java官方文档,了解每个类的完整API列表
- 实际应用:尝试将所学知识应用到实际项目中,如用户输入验证、数据清洗等
通过本章学习,你应该掌握了Java标准类库中字符串和包装器类的核心用法,能够熟练处理字符串操作、正则表达式匹配以及数据类型转换等常见任务。这些知识是Java编程的基础,将在后续的学习和开发中频繁使用。
更多推荐


所有评论(0)