1. String 概述
核心概念
-
Java API:Java 提供的一套预定义类和接口,可以直接使用
-
String 类 :
java.lang.String代表字符串,程序中所有字符串字面值都是该类的对象 -
重要特性 :String 对象是不可变的(immutable),创建后内容不能修改
2. 创建 String 对象的四种方式
方式1:直接赋值(最常用)
java
// 语法:String 变量名 = "字符串内容";
String str1 = "Hello World";
String str2 = "Java";
String emptyStr = ""; // 空字符串
// 特点:会检查字符串池,如果已存在则复用
String s1 = "abc";
String s2 = "abc"; // s1 和 s2 指向同一个对象
System.out.println(s1 == s2); // true,地址相同
方式2:new String() 构造方法
java
// 1. 创建空白字符串
String str1 = new String(); // 等价于 ""
System.out.println(str1); // 输出:空字符串
System.out.println(str1.length()); // 输出:0
// 2. 根据已有字符串创建
String original = "Hello";
String str2 = new String(original); // 创建新的String对象,内容为"Hello"
// 3. 根据字符数组创建
char[] charArray = {'J', 'a', 'v', 'a'};
String str3 = new String(charArray); // "Java"
String str4 = new String(charArray, 0, 2); // 从索引0开始取2个字符:"Ja"
// 4. 根据字节数组创建(常用于网络传输、文件读写)
byte[] byteArray = {65, 66, 67, 68}; // ASCII: A, B, C, D
String str5 = new String(byteArray); // "ABCD"
// 指定字符集
try {
byte[] bytes = "你好".getBytes("UTF-8");
String str6 = new String(bytes, "UTF-8"); // "你好"
} catch (Exception e) {
e.printStackTrace();
}
3. String 类的常用方法
长度和空值判断
java
String str = "Hello Java";
// 获取长度
int length = str.length(); // 10
// 判断是否为空
boolean isEmpty = str.isEmpty(); // false
boolean isEmpty2 = "".isEmpty(); // true
// 判断是否为空白(包含空格、制表符等)
boolean isBlank = " ".isBlank(); // true(Java 11+)
字符串比较
java
String s1 = "abc";
String s2 = "abc";
String s3 = new String("abc");
String s4 = "ABC";
// 使用 == 比较(比较地址)
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false(s3在堆内存中)
// 使用 equals() 比较(比较内容)
System.out.println(s1.equals(s2)); // true
System.out.println(s1.equals(s3)); // true
System.out.println(s1.equals(s4)); // false(区分大小写)
// 忽略大小写比较
System.out.println(s1.equalsIgnoreCase(s4)); // true
// 比较字符串字典顺序
System.out.println("abc".compareTo("abd")); // -1(小于)
System.out.println("abc".compareTo("abc")); // 0(等于)
System.out.println("abd".compareTo("abc")); // 1(大于)
字符串查找
java
String str = "Hello Java World";
// 查找字符/字符串位置
int index1 = str.indexOf('J'); // 6(第一个J的位置)
int index2 = str.indexOf("Java"); // 6
int index3 = str.indexOf('a', 7); // 8(从索引7开始查找)
// 从后往前查找
int lastIndex = str.lastIndexOf('o'); // 13
// 是否包含
boolean contains = str.contains("Java"); // true
// 是否以指定字符串开始/结束
boolean startsWith = str.startsWith("Hello"); // true
boolean endsWith = str.endsWith("World"); // true
字符串截取和替换
java
String str = "Hello Java World";
// 截取子串
String sub1 = str.substring(6); // "Java World"(从索引6到结尾)
String sub2 = str.substring(6, 10); // "Java"(从6到9,不包含10)
// 替换
String replaced1 = str.replace('o', 'O'); // "HellO Java WOrld"
String replaced2 = str.replace("Java", "Python"); // "Hello Python World"
// 替换所有(正则表达式)
String replaced3 = str.replaceAll("\\s+", "-"); // 将所有空白替换为-
字符串分割和连接
java
// 分割字符串
String str = "apple,banana,orange";
String[] fruits = str.split(","); // ["apple", "banana", "orange"]
// 复杂分割(正则表达式)
String complex = "apple, banana; orange";
String[] result = complex.split("[,\\s;]+"); // 按逗号、空格、分号分割
// 连接字符串
String joined = String.join("-", "Java", "Python", "C++"); // "Java-Python-C++"
大小写转换和去除空白
java
String str = " Hello Java ";
// 大小写转换
String upper = str.toUpperCase(); // " HELLO JAVA "
String lower = str.toLowerCase(); // " hello java "
// 去除首尾空白
String trimmed = str.trim(); // "Hello Java"
// 去除首尾空白(包含Unicode空白符)
String stripped = str.strip(); // "Hello Java"(Java 11+)
其他常用方法
java
String str = "Java";
// 获取指定位置的字符
char ch = str.charAt(2); // 'v'
// 转换为字符数组
char[] chars = str.toCharArray(); // ['J', 'a', 'v', 'a']
// 转换为字节数组
byte[] bytes = str.getBytes(); // 使用平台默认编码
// 格式化字符串
String formatted = String.format("姓名:%s,年龄:%d", "张三", 25);
// 重复字符串
String repeated = "Java ".repeat(3); // "Java Java Java "(Java 11+)
4. String 的不可变性
不可变性的表现
java
String s1 = "Hello";
String s2 = s1; // s1和s2指向同一个对象
s1 = s1 + " World"; // 创建新的String对象
System.out.println(s1); // "Hello World"
System.out.println(s2); // "Hello"(s2不受影响)
不可变性的好处
-
线程安全:无需同步
-
缓存哈希值:提高性能
-
字符串池:节省内存
-
安全性:防止被修改
5. 字符串常量池
内存机制
java
// 情况1:直接赋值(使用常量池)
String s1 = "abc"; // 检查常量池,如果不存在则创建
String s2 = "abc"; // 复用常量池中的对象
System.out.println(s1 == s2); // true
// 情况2:new String()(在堆内存创建新对象)
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3 == s4); // false
System.out.println(s1 == s3); // false
// 情况3:intern()方法(手动入池)
String s5 = s3.intern(); // 将s3的内容放入常量池
System.out.println(s1 == s5); // true
6. 性能优化建议
避免使用 + 连接大量字符串
java
// 错误做法(创建多个临时对象)
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // 每次循环创建新的String对象
}
// 正确做法(使用StringBuilder)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String result = sb.toString();
7. 实际应用示例
示例1:用户输入验证
java
import java.util.Scanner;
public class StringDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = scanner.nextLine().trim();
// 验证用户名
if (username.isEmpty()) {
System.out.println("用户名不能为空!");
} else if (username.length() < 3) {
System.out.println("用户名至少3个字符!");
} else if (!username.matches("[a-zA-Z0-9_]+")) {
System.out.println("用户名只能包含字母、数字和下划线!");
} else {
System.out.println("用户名有效:" + username);
}
}
}
示例2:文件路径处理
java
public class FilePathDemo {
public static void main(String[] args) {
String filePath = "C:/Users/User/Documents/test.txt";
// 获取文件名
int lastSlash = filePath.lastIndexOf('/');
String fileName = filePath.substring(lastSlash + 1);
System.out.println("文件名:" + fileName); // test.txt
// 获取文件扩展名
int dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0) {
String extension = fileName.substring(dotIndex + 1);
System.out.println("扩展名:" + extension); // txt
}
// 获取文件路径
String directory = filePath.substring(0, lastSlash);
System.out.println("目录:" + directory); // C:/Users/User/Documents
}
}