📚 核心目录
⚙️ 字符串的本质特性
不可变性原理
public final class String { private final char value[]; private int hash; // ... }
String对象头
hash字段
value引用
char数组
不可变性的三大优势
-
线程安全保证
-
哈希值缓存优化
-
字符串常量池基础
字符串常量池探秘
内存分布示意图
35%65%堆内存分布字符串常量池其他对象
intern()方法机制
String s1 = new String("Hello"); s1.intern(); // 将字符串放入常量池(JDK7+)
⚠️ JDK1.7后字符串常量池移到堆内存,允许回收不在引用的常量
⚡ 字符串操作性能对比
追加操作基准测试
// 使用+拼接 String result = ""; for(int i=0; i<10000; i++) { result += i; // 产生大量临时对象 } // StringBuilder优化 StringBuilder sb = new StringBuilder(); for(int i=0; i<10000; i++) { sb.append(i); // 单对象操作 }
操作方式 | 10万次耗时(ms) | 内存消耗(MB) |
---|---|---|
+ 运算符 | 4523 | 58.7 |
concat方法 | 3971 | 52.3 |
StringBuilder | 23 | 1.2 |
StringBuilder核心源码解析
自动扩容机制
void expandCapacity(int minimumCapacity) { int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; value = Arrays.copyOf(value, newCapacity); }
关键参数优化
// 初始容量计算公式 int initialCapacity = 预估长度 + (预估长度 >> 1); // 推荐1.5倍冗余空间
🌐 编码问题全解
编码转换陷阱
String str = "你好"; byte[] bytes1 = str.getBytes("GBK"); String str2 = new String(bytes1, "UTF-8"); // 产生乱码
最佳转换实践
// 显示指定编码类型 String data = new String(bytes, StandardCharsets.UTF_8); byte[] output = data.getBytes(StandardCharsets.UTF_8);
JDK新特性
Java 9紧凑字符串
// 启用-XX:-CompactStrings可禁用 public final class String { private final byte[] value; // 改用字节数组存储 private final byte coder; // 0-Latin1, 1-UTF16 }
新API示例
// Java 11新增方法 String formatted = "Java %s".formatted("11"); // 格式化字符串 String repeat = "AB".repeat(3); // "ABABAB" String strip = " Unicode ".strip(); // 去首尾空白
🔒 安全风险防范
SQL注入防护
// 危险写法 String query = "SELECT * FROM users WHERE name=" + userInput; // 安全写法 PreparedStatement stmt = conn.prepareStatement( "SELECT * FROM users WHERE name=?"); stmt.setString(1, userInput);
敏感信息处理
String password = "123456"; Arrays.fill(passwordChars, '\0'); // 及时清除内存数据
🎯 高频面试题精解
Q1:String、StringBuilder、StringBuffer区别?
特征 | String | StringBuilder | StringBuffer |
---|---|---|---|
可变性 | 不可变 | 可变 | 可变 |
线程安全 | 线程安全 | 非线程安全 | 线程安全 |
性能优势 | 适合常量操作 | 单线程首选 | 安全场景使用 |
🚀 性能优化宝典
1. 大文本处理方案
// 分块读取优化 try (BufferedReader br = new BufferedReader(new FileReader(path))) { String line; StringBuilder buffer = new StringBuilder(1024); while ((line = br.readLine()) != null) { buffer.append(line).append("\n"); } }
2. 正则表达式预编译
private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$"); boolean isValid = EMAIL_PATTERN.matcher(email).matches();
⚠️ 典型错误示例
错误写法案例集
// 反复拼接新字符串 String fullName = ""; for (String part : nameParts) { fullName += part; } // 未判断空值的分隔 String[] parts = input.split(","); if (input == null || input.isEmpty()) { // 需要处理空值情况 } // 字符串比较错误 if (authCode == "ABC123") { // 应该使用equals // ... }
思考与挑战
-
如何实现O(1)空间复杂度的字符串反转?
-
什么场景下应当优先使用String.join()方法?
-
为什么Java保留String的特殊操作符+重载?