Java 字符串从基础到高级应用详解
作者:石山代码
在Java中,字符串(String)是使用非常广泛的数据类型之一,它们是不可变的,这意味着一旦创建,字符串的内容就不能被改变,本文给大家介绍Java 字符串从基础到高级应用详解,感兴趣的朋友一起看看吧
1. 什么是 Java 字符串?
在 Java 中,字符串(String)是一个不可变的字符序列,用于表示文本数据。它是 Java 中最常用、最重要的类之一,位于 java.lang 包中,因此无需显式导入即可使用。
Java 字符串的核心特点:
- 不可变性(Immutable):一旦创建,字符串的内容就不能被修改。任何看似修改的操作(如拼接、替换)实际上都会创建一个新的字符串对象。
- 字符串常量池(String Pool):Java 虚拟机(JVM)为字符串字面量维护了一个特殊的内存区域,用于优化内存使用和性能。
- Unicode 支持:Java 字符串内部使用 UTF-16 编码,可以表示全球大多数语言的字符。
2. 创建字符串的三种方式
Java 提供了多种创建字符串的方式,每种方式在内存分配和行为上有所不同。
2.1 使用字符串字面量
String str1 = "Hello, Java!"; String str2 = "Hello, Java!"; // 复用常量池中的对象
这种方式创建的字符串会被放入字符串常量池。如果常量池中已存在相同内容的字符串,则直接引用该对象,不会创建新对象。
2.2 使用 new 关键字
String str3 = new String("Hello, Java!");
String str4 = new String("Hello, Java!"); // 创建新的对象使用 new 关键字会在堆内存中创建新的字符串对象,即使内容相同也会创建不同的对象。
2.3 使用字符数组
char[] charArray = {'J', 'a', 'v', 'a'};
String str5 = new String(charArray); // "Java"3. 字符串常用操作
3.1 获取字符串信息
String str = "Hello, World!";
// 获取长度
int length = str.length(); // 13
// 获取指定位置的字符
char ch = str.charAt(0); // 'H'
// 获取子字符串
String sub1 = str.substring(7); // "World!"
String sub2 = str.substring(0, 5); // "Hello"
// 查找字符或子串
int index1 = str.indexOf('o'); // 4
int index2 = str.indexOf("World"); // 7
int lastIndex = str.lastIndexOf('o'); // 83.2 字符串比较
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
String s4 = "JAVA";
// 使用 equals() 比较内容
boolean b1 = s1.equals(s2); // true
boolean b2 = s1.equals(s3); // true
boolean b3 = s1.equals(s4); // false
// 使用 equalsIgnoreCase() 忽略大小写比较
boolean b4 = s1.equalsIgnoreCase(s4); // true
// 使用 == 比较引用
boolean b5 = (s1 == s2); // true(都指向常量池)
boolean b6 = (s1 == s3); // false(s3 是堆中新对象)3.3 字符串修改操作
String original = " Hello Java ";
// 去除首尾空格
String trimmed = original.trim(); // "Hello Java"
// 替换字符或子串
String replaced1 = original.replace('a', 'A'); // " Hello JAvA "
String replaced2 = original.replace("Java", "World"); // " Hello World "
// 大小写转换
String upper = original.toUpperCase(); // " HELLO JAVA "
String lower = original.toLowerCase(); // " hello java "
// 分割字符串
String csv = "apple,banana,orange";
String[] fruits = csv.split(","); // ["apple", "banana", "orange"]4. 字符串拼接与性能优化
4.1 拼接方式对比
// 1. 使用 + 运算符(编译时优化)
String result1 = "Hello" + " " + "World";
// 2. 使用 concat() 方法
String result2 = "Hello".concat(" ").concat("World");
// 3. 使用 StringBuilder(可变,线程不安全)
StringBuilder sb1 = new StringBuilder();
sb1.append("Hello").append(" ").append("World");
String result3 = sb1.toString();
// 4. 使用 StringBuffer(可变,线程安全)
StringBuffer sb2 = new StringBuffer();
sb2.append("Hello").append(" ").append("World");
String result4 = sb2.toString();4.2 性能建议
- 单次拼接或少量拼接:使用
+运算符,代码简洁,编译器会优化。 - 循环内拼接:使用
StringBuilder,避免创建大量临时字符串对象。 - 多线程环境:使用
StringBuffer,但性能略低于StringBuilder。
5. 字符串与字符数组的转换
// 字符串转字符数组
String str = "Java";
char[] charArray = str.toCharArray();
// 字符数组转字符串
char[] chars = {'J', 'a', 'v', 'a'};
String fromChars1 = new String(chars);
String fromChars2 = String.valueOf(chars);
String fromChars3 = String.copyValueOf(chars);6. 字符串格式化
// 使用 String.format()
String name = "张三";
int age = 25;
double score = 95.5;
String info = String.format("姓名:%s,年龄:%d,分数:%.1f", name, age, score);
// 结果:"姓名:张三,年龄:25,分数:95.5"
// 使用 printf 风格(直接输出)
System.out.printf("姓名:%s,年龄:%d%n", name, age);7. 字符串常量池与 intern() 方法
intern() 方法可以将字符串对象添加到常量池中,或返回常量池中已存在的相同内容的字符串引用。
String s1 = new String("Java");
String s2 = s1.intern();
String s3 = "Java";
System.out.println(s1 == s2); // false
System.out.println(s2 == s3); // true8. 实际应用示例
8.1 用户输入验证
public class InputValidator {
public static boolean isValidEmail(String email) {
if (email == null || email.trim().isEmpty()) {
return false;
}
return email.contains("@") && email.contains(".");
}
public static boolean isValidPhone(String phone) {
if (phone == null) return false;
String trimmed = phone.trim();
return trimmed.matches("\\d{11}"); // 11位数字
}
}8.2 文件路径处理
public class PathUtils {
public static String getFileName(String filePath) {
if (filePath == null || filePath.isEmpty()) {
return "";
}
int lastSlash = filePath.lastIndexOf('/');
int lastBackslash = filePath.lastIndexOf('\\');
int lastSeparator = Math.max(lastSlash, lastBackslash);
if (lastSeparator == -1) {
return filePath;
}
return filePath.substring(lastSeparator + 1);
}
}9. 常见面试题解析
9.1 String、StringBuilder、StringBuffer 的区别
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 是(因为不可变) | 否 | 是 |
| 性能 | 较低(频繁修改时) | 高 | 中等 |
| 使用场景 | 常量字符串、键值 | 单线程字符串操作 | 多线程字符串操作 |
9.2 为什么 String 要设计为不可变?
- 安全性:字符串常用于网络连接、文件路径、数据库连接等敏感操作,不可变性可以防止被篡改。
- 线程安全:不可变对象天生线程安全,可以在多线程环境中安全共享。
- 缓存哈希值:String 的
hashCode()值在第一次计算后缓存,提高哈希表性能。 - 字符串常量池:不可变性是实现字符串常量池的基础,可以节省内存。
10. 总结
Java 字符串是编程中最基础也是最重要的数据类型之一。理解其不可变性、常量池机制以及不同拼接方式的性能差异,对于编写高效、可靠的 Java 程序至关重要。在实际开发中,应根据具体场景选择合适的字符串操作方式,并注意避免常见的内存和性能问题。
到此这篇关于Java 字符串从基础到高级应用详解的文章就介绍到这了,更多相关Java 字符串应用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
