java 怎么用string
- 后端开发
- 2025-08-05
- 6
new String()
创建对象;用
+
拼接字符串、
length()
取长度、
charAt(index)
按索引取字符等操作来使用
String。
Java中,String
类是处理文本数据的核心工具,其设计具有不可变性、线程安全性和丰富的API支持等特点,以下是关于如何使用Java中String
类的详细指南:
创建字符串的方式
-
字面量直接赋值
这是最常用的方式,通过双引号包裹字符序列即可创建字符串对象。String str1 = "Hello";
,此时JVM会检查字符串常量池中是否已存在相同内容的字符串,若存在则复用该对象;否则新建并存入池中,这种方式效率高且节省内存,需要注意的是,两个相同的字面量创建的字符串引用地址相同(如str1 == str2
结果为true
)。 -
使用new关键字构造
通过new String(...)
显式创建对象时,无论内容是否重复都会生成新实例并存放在堆内存中。String str3 = new String("Hello");
,即使与字面量的值相同,new
出来的对象地址也不同(str1 != str3
),适用于需要独立副本的场景。 -
基于数组初始化
- 字符数组转换:先将字符存入数组再构造字符串,示例:
char[] chars = {'J','a','v','a'}; String str4 = new String(chars); // 结果:"Java"
- 字节流解码:指定编码格式将字节数组转为字符串,常用于I/O操作后的数据处理:
byte[] bytes = {74, 97, 118, 97}; // ASCII对应"Java" String str5 = new String(bytes, StandardCharsets.UTF_8);
- 字符数组转换:先将字符存入数组再构造字符串,示例:
-
动态构建工具类转化
当需要频繁修改内容时,建议先用StringBuilder
或StringBuffer
拼接,最后转为String
类型,两者区别主要在于线程安全(StringBuffer
同步而StringBuilder
非同步):StringBuilder builder = new StringBuilder(); builder.append("Java").append("编程"); String finalStr = builder.toString(); // "Java编程"
常用方法及功能解析
方法名 | 作用 | 示例代码 | 注意事项 |
---|---|---|---|
length() |
返回字符串长度(Unicode字符数) | "中文".length() → 2 |
区别于数组的.length 属性 |
charAt(int index) |
获取指定位置的单个字符 | str.charAt(0) |
索引从0开始,越界抛异常 |
substring(int...) |
截取子串,支持单参数(起始点到末尾)或双参数(起止区间) | "ABCDE".substring(1,3) → "BC" |
结束索引不包含在内 |
indexOf(String/chr) |
查找首次出现的位置,未找到返回-1 | "apple".indexOf('p') → 1 |
可指定起始搜索位置 |
contains(CharSeq) |
判断是否包含某子串 | "hello".contains("ell") → true |
内部依赖indexOf 实现 |
toUpperCase() |
转为全大写形式 | "test".toUpperCase() → "TEST" |
原字符串不变,返回新对象 |
trim() |
去除首尾空白符(空格、制表符等) | " Java ".trim() → "Java" |
不影响中间空格 |
split(regex) |
根据正则表达式分割成数组 | ", ".split(",") →[“a”,”b”,”c”] |
特殊符号需转义,如"\|" |
replaceAll(regex, replacement) |
全局替换匹配正则的部分 | "a1b2".replaceAll("\d", "X") → "aXbX" |
第一个参数必须是有效正则表达式 |
重要特性与原理
-
不可变性
所有看似修改的操作(如拼接、替换)实际都会生成新对象,原始数据保持不变,这种设计带来三大优势:- 线程安全:多线程并发访问无需同步控制;
- 哈希缓存优化:字符串的哈希值只需计算一次;
- 安全性保障:防止敏感数据被意外改动。
String s = "original"; s += "_suffix"; // 实际创建了新对象,原对象仍为"original"
-
字符串常量池机制
JVM通过驻留于方法区的字符串池实现存储优化,当使用字面量或调用intern()
方法时,会尝试将字符串加入池中,典型表现如下:String a = "abc"; String b = "abc"; // a和b指向同一对象 String c = new String("abc"); // 新对象不在池中 String d = c.intern(); // d重新指向池中的"abc"
-
性能考量
- 避免频繁拼接:在循环中使用连接字符串会产生大量临时对象,推荐改用
StringBuilder
; - 慎用正则表达式:
split()
和replaceAll()
使用的正则较耗性能,简单场景可用普通方法替代; - 空校验优先:调用方法前建议判断是否为
null
,防止NPE异常。
- 避免频繁拼接:在循环中使用连接字符串会产生大量临时对象,推荐改用
典型应用场景示例
-
用户输入处理:从控制台读取命令时通常伴随多余空格,可用
trim()
清理:Scanner scanner = new Scanner(System.in); String input = scanner.nextLine().trim();
-
文件路径解析:利用
startsWith()
/endsWith()
快速验证扩展名:if (filePath.endsWith(".txt")) { / 处理文本文件 / }
-
模板渲染:结合
format()
实现变量插值:String template = String.format("用户%s来自%s", name, city);
以下是针对常见问题的解答:
FAQs
Q1: 如何高效拼接大量字符串?
A: 使用StringBuilder
代替直接使用运算符,因为在编译时会自动转换为StringBuffer
,但在循环中多次调用会产生较多中间对象,而StringBuilder
直接在可变缓冲区操作,性能更优。
StringBuilder sb = new StringBuilder(); for (int i=0; i<1000; i++) { sb.append(i).append(","); } String result = sb.toString(); // 仅一次对象创建
Q2: 为什么不能用==比较两个字符串的内容?
A: 比较的是对象的内存地址而非内容,即使两个字符串值相同,若分别通过字面量和new创建,它们的引用地址不同会导致误判,应始终使用equals()
方法进行内容比较。
String s1 = new String("hello"); String s2 = new String("hello"); System.out.println(s1 == s2); // false(不同对象) System.out.println(s1.equals(s2)); //