JAVA:String类详解
初识String——字符串的本质是什么?
现实场景:想象你要开发一个用户注册系统,需要处理用户名、密码、邮箱等文本信息。这些文本数据在Java中如何表示?答案就是String
类。
String的定义:
String
是Java中用于表示文本数据的核心类,每个双引号""
包裹的字符序列都是String
对象。
基础示例:
// 直接量创建
String greeting = "Hello World!";
System.out.println(greeting); // 输出:Hello World!// 构造函数创建
String name = new String("Alice");
System.out.println(name); // 输出:Alice
第一章:深入String的不可变性——为什么字符串不可变?
1.1 不可变性的直观理解
实验代码:
String s1 = "Java";
s1 = s1 + " Programming";
System.out.println(s1); // 输出:Java Programming
疑问:看起来s1
被修改了,为什么说String不可变?
1.2 内存模型解析
原始状态:
栈内存 堆内存(字符串池)
s1 --> "Java"修改后状态:
s1 --> "Java Programming"(新对象)
原"Java"对象仍然存在
关键结论:
- 每次字符串修改都创建新对象
- 原对象内容永不改变
1.3 不可变性的优势
- 线程安全:无需同步即可多线程共享
- 缓存哈希值:提升哈希表性能
- 字符串池优化:减少内存开销
- 安全性:防止敏感信息被篡改
第二章:字符串池(String Pool)——高效管理的秘密
2.1 字符串池原理
内存结构:
字符串池(堆内存)
+-------------------+
| "Java" |
| "Hello" |
| "Alice" |
+-------------------+
2.2 两种创建方式的区别
String s1 = "Java"; // 直接量:优先使用池中对象
String s2 = new String("Java"); // 强制创建新对象
内存示意图:
栈内存 堆内存
s1 --> 池中"Java"
s2 --> 新对象"Java"
2.3 intern()方法
String s3 = new String("Java").intern();
System.out.println(s1 == s3); // true,返回池中已有对象
第三章:字符串操作大全——常用方法详解
3.1 基础查询方法
String text = "Java Programming";// 获取长度
int len = text.length(); // 15// 获取字符
char ch = text.charAt(4); // ' '(空格)// 查找索引
int index = text.indexOf("Pro"); // 5
3.2 字符串比较
// 内容比较(正确方式)
boolean eq1 = "Java".equals("java"); // false(区分大小写)
boolean eq2 = "Java".equalsIgnoreCase("JAVA"); // true// 错误比较方式
String s1 = new String("Test");
String s2 = new String("Test");
System.out.println(s1 == s2); // false(比较对象地址)
3.3 字符串截取与分割
// 子字符串
String sub = text.substring(5); // "Programming"
String sub2 = text.substring(5, 12); // "Program"// 分割为数组
String[] parts = "A,B,C".split(","); // ["A", "B", "C"]
3.4 字符串修改
// 替换内容
String newText = text.replace("Java", "Python"); // 去除首尾空格
String clean = " Hello ".trim(); // "Hello"// 大小写转换
String upper = text.toUpperCase(); // "JAVA PROGRAMMING"
第四章:字符串拼接的艺术——性能优化指南
4.1 拼接方式对比
// 方式1:+运算符
String result = "A" + "B" + "C"; // 编译优化为StringBuilder// 方式2:concat方法
String s = "Hello".concat(" World");// 方式3:StringBuilder(推荐循环中使用)
StringBuilder sb = new StringBuilder();
sb.append("A").append("B").append("C");
String res = sb.toString();
4.2 性能测试
// 测试代码
long start = System.currentTimeMillis();
String s = "";
for(int i=0; i<100000; i++) {s += i; // 每次循环创建新对象
}
long end = System.currentTimeMillis();
System.out.println("+耗时:" + (end-start) + "ms");// 使用StringBuilder优化
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for(int i=0; i<100000; i++) {sb.append(i);
}
end = System.currentTimeMillis();
System.out.println("StringBuilder耗时:" + (end-start) + "ms");
典型结果:
+耗时:4321ms
StringBuilder耗时:8ms
第五章:String与其他类的对比
5.1 String vs StringBuffer vs StringBuilder
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 是 | 是(同步方法) | 否 |
性能 | 低(频繁修改) | 中 | 高 |
使用场景 | 常量字符串 | 多线程环境修改 | 单线程环境修改 |
5.2 转换方法
// String与其他类型互转
int num = 123;
String s1 = String.valueOf(num); // "123"
int back = Integer.parseInt(s1); // 123// 字符数组转换
char[] arr = {'J','a','v','a'};
String s2 = new String(arr); // "Java"
char[] arr2 = s2.toCharArray();
第六章:正则表达式与字符串处理
6.1 基础匹配
String email = "user@example.com";
boolean isValid = email.matches("[a-zA-Z0-9]+@[a-z]+\\.[a-z]{2,3}");
6.2 复杂替换
String text = "订单号:ORD123456,金额:$599.99";
String masked = text.replaceAll("\\d{6}", "******");
// 输出:订单号:ORD******,金额:$599.99
6.3 分组提取
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher("2023-10-01");
if(matcher.find()) {System.out.println("年:" + matcher.group(1)); // 2023System.out.println("月:" + matcher.group(2)); // 10
}
第七章:字符串编码与国际化
7.1 字符编码转换
// UTF-8与GBK转换
String chinese = "你好";
byte[] utf8Bytes = chinese.getBytes(StandardCharsets.UTF_8);
String decoded = new String(utf8Bytes, "GBK"); // 乱码!// 正确转换方式
byte[] gbkBytes = chinese.getBytes("GBK");
String correct = new String(gbkBytes, "GBK"); // 正确显示
7.2 国际化处理
// 资源文件加载
ResourceBundle bundle = ResourceBundle.getBundle("Messages", Locale.US);
String greeting = bundle.getString("welcome"); // "Hello"
第八章:常见陷阱与最佳实践
8.1 典型错误
// 错误1:循环内字符串拼接
String result = "";
for(int i=0; i<10000; i++) {result += i; // 产生大量临时对象
}// 错误2:忽略编码问题
String s = new String(bytes); // 使用平台默认编码// 错误3:错误比较
if(password == "secret") { ... } // 应该用equals
8.2 最佳实践
- 优先使用直接量:
String s = "text"
- 复杂操作用StringBuilder
- 明确指定字符编码
- 敏感信息用char[]
// 安全处理密码
char[] password = request.getPassword();
// 使用后立即清除
Arrays.fill(password, '\0');
九.综合案例——开发文本分析工具
9.1 需求分析
- 统计文本中的单词频率
- 查找最长单词
- 替换敏感词
- 生成词云数据
9.2 完整实现
public class TextAnalyzer {public static void main(String[] args) {String text = "Java is to JavaScript what car is to carpet.";// 1. 单词频率统计Map<String, Integer> freq = new HashMap<>();for(String word : text.split("\\W+")) {freq.put(word, freq.getOrDefault(word, 0)+1);}System.out.println("词频:" + freq);// 2. 查找最长单词String longest = Arrays.stream(text.split("\\W+")).max(Comparator.comparingInt(String::length)).orElse("");System.out.println("最长单词:" + longest);// 3. 敏感词过滤String filtered = text.replaceAll("(?i)java", "J***");System.out.println("过滤后:" + filtered);}
}
总结:
- String类的核心特性与内存机制
- 字符串操作的全套方法
- 性能优化关键技巧
- 编码与国际化处理
- 常见陷阱规避方法
- 现代Java文本处理特性