编程自学指南:java程序设计开发,String详细解析
学习目标:
-
理解String的不可变性及其底层实现
-
掌握String常用方法与性能优化技巧
-
能够通过String操作解决实际问题
-
避免字符串处理中的常见陷阱
一、课程引入
1.1 String的重要性
-
应用场景:数据处理、日志记录、网络通信、用户输入验证
-
Java中的特殊地位:唯一支持运算符重载的类(
+
)
1.2 String核心特性
-
不可变性(Immutability):对象一旦创建,内容不可修改
-
字符串常量池(String Pool):JVM优化内存的机制
二、String不可变性与内存结构
2.1 不可变性的实现
public final class String implements Serializable, Comparable<String>, CharSequence {
private final char value[]; // Java 8及之前
private final byte[] value; // Java 9+(LATIN1/UTF-16编码优化)
// ...
}
2.2 字符串常量池
案例1:字符串创建方式对比
String s1 = "Java"; // 常量池中创建
String s2 = new String("Java"); // 堆中创建新对象
System.out.println(s1 == s2); // false(地址不同)
System.out.println(s1.equals(s2)); // true(内容相同)
2.3 intern()方法
String s3 = new String("Hello").intern();
String s4 = "Hello";
System.out.println(s3 == s4); // true
三、String常用方法解析
3.1 字符串比较与操作
方法 | 说明 | 示例(假设str = "Hello Java") |
---|---|---|
length() | 返回字符串长度 | str.length() → 10 |
charAt(int index) | 返回指定索引的字符 | str.charAt(4) → 'o' |
substring(int begin) | 截取子字符串 | str.substring(6) → "Java" |
split(String regex) | 按正则表达式分割字符串 | str.split(" ") → ["Hello", "Java"] |
replace(old, new) | 替换字符/字符串 | str.replace("Java", "World") → "Hello World" |
案例2:用户输入验证
public boolean isValidEmail(String email) {
return email != null && email.matches("^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$");
}
3.2 字符串转换
方法 | 说明 |
---|---|
toUpperCase() /toLowerCase() | 大小写转换 |
trim() | 去除首尾空白 |
valueOf(Object obj) | 将对象转为字符串 |
案例3:金额格式化
double amount = 1234567.89;
String formatted = String.format("%,.2f", amount); // "1,234,567.89"
四、String性能优化
4.1 字符串拼接性能对比
方式 | 适用场景 |
---|---|
+ 运算符 | 少量固定字符串拼接 |
StringBuilder | 单线程下大量修改 |
StringBuffer | 多线程下安全修改(同步锁) |
案例4:拼接10万次字符串耗时对比
// 使用+运算符(性能最差)
String result = "";
for (int i = 0; i < 100000; i++) {
result += i;
}
// 使用StringBuilder(性能最优)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
4.2 避免内存泄漏
案例5:错误使用substring(Java 6及之前)
String bigString = new String(new byte[1000000]);
String sub = bigString.substring(0, 2);
// Java 6中sub仍引用原大数组,导致内存泄漏
五、综合应用案例
5.1 案例6:统计字符出现次数
public Map<Character, Integer> countChars(String input) {
Map<Character, Integer> map = new HashMap<>();
for (char c : input.toCharArray()) {
map.put(c, map.getOrDefault(c, 0) + 1);
}
return map;
}
// 测试
countChars("programming"); // {p=1, r=2, o=1, g=2, ...}
5.2 案例7:敏感信息脱敏
public String maskPhone(String phone) {
if (phone == null || phone.length() < 7) return phone;
return phone.substring(0, 3) + "****" + phone.substring(7);
}
maskPhone("13812345678"); // "138****5678"
六、常见问题与最佳实践
6.1 常见错误
-
错误1:忽略编码问题
new String(bytes); // 默认使用平台编码,可能乱码 new String(bytes, StandardCharsets.UTF_8); // 正确方式
-
错误2:滥用
==
比较字符串String s1 = new String("Hi"); String s2 = new String("Hi"); if (s1 == s2) { /* 永远不会执行 */ }
6.2 最佳实践
-
优先使用
equals()
比较内容 -
多语言支持:始终明确指定字符编码
-
敏感数据处理:及时清空
char[]
(如密码)
七、总结与练习
7.1 总结
-
不可变性:安全、线程安全、支持字符串池优化
-
性能关键:避免大量拼接,合理选择
StringBuilder
-
编码规范:统一使用UTF-8,正确处理国际化
7.2 课后任务
-
实现一个方法,将字符串中的单词逆序(如"Hello World" → "World Hello")
-
编写程序检测字符串是否为回文(忽略大小写和标点)
-
预习下一节课:正则表达式深入
7.3 扩展挑战
-
实现一个简单的模板引擎(如替换
${name}
为实际值)