在 Java 编程中,字符串操作、基本类型包装以及日期时间处理是日常开发中高频出现的场景。掌握这些知识点不仅能提升代码效率,更能避免一些隐藏的坑。本文将系统讲解 String 字符串、可变字符串、八大包装类及日期处理的核心知识与实践技巧。

一、字符串:不可变的字符序列
String 类是 Java 中最常用的类之一,它的不可变性是理解其特性的关键。
1. 核心特性解析
- 不可继承:String 被
final修饰,无法被其他类继承。 - 不可变对象:字符串一旦创建,其内部字符序列就不可修改。任何修改操作(如拼接、替换)都会生成新的 String 对象。
- 两种创建方式:
// 字面量方式:创建于字符串常量池,相同内容会复用 String s1 = "hello"; // new方式:创建于堆内存,每次new都会生成新对象 String s2 = new String("hello"); System.out.println(s1 == s2); // 输出false(地址不同) System.out.println(s1.equals(s2)); // 输出true(内容相同)
2. 常用方法实战
String 类提供了丰富的方法用于字符串操作,以下是开发中最常用的 API:
| 方法分类 | 关键方法 | 功能说明 |
|---|---|---|
| 基础信息 | length() | 返回字符串长度 |
charAt(int index) | 获取指定索引的字符(索引从 0 开始) | |
| 查找操作 | indexOf(String str) | 查找子串首次出现的索引,不存在返回 - 1 |
lastIndexOf(String str) | 查找子串最后出现的索引 | |
| 截取拼接 | substring(int begin) | 从 begin 索引截取到末尾 |
substring(int begin, int end) | 截取 [begin, end) 区间的子串 | |
concat(String str) | 拼接字符串(等价于+,但效率更高) | |
| 修改转换 | replace(CharSequence old, CharSequence new) | 替换子串 |
split(String regex) | 按正则分割为字符串数组 | |
toUpperCase()/toLowerCase() | 转换大小写 | |
toCharArray() | 转为字符数组 | |
| 类型转换 | valueOf(任意类型) | 静态方法,将其他类型转为字符串 |
示例代码:
public class StringDemo {
public static void main(String[] args) {
String str = "Java Programming";
// 基础操作
System.out.println("长度:" + str.length()); // 18
System.out.println("第5个字符:" + str.charAt(4)); // 空格
// 查找与截取
int index = str.indexOf("Program");
System.out.println("Program起始索引:" + index); // 5
System.out.println("截取子串:" + str.substring(5, 12)); // Program
// 替换与分割
String replaced = str.replace("Programming", "Coding");
System.out.println("替换后:" + replaced); // Java Coding
String[] parts = str.split(" ");
System.out.println("分割结果:" + parts[0] + "|" + parts[1]); // Java|Programming
}
}
-
toCharArray()是String类的方法,作用是将字符串转换为字符数组(char[])。例如:String str = "hello"; char[] arr = str.toCharArray(); // arr 结果为 {'h','e','l','l','o'} -
String.valueOf(char[])是String类的静态方法,作用是将字符数组(char[])转换为字符串(String),正好与toCharArray()相反。例如:char[] arr = {'h','i'}; String str = String.valueOf(arr); // str 结果为 "hi"
二、可变字符串:StringBuilder 与 StringBuffer
当需要频繁修改字符串时,使用 String 会产生大量临时对象,导致性能问题。此时应选择可变字符串类。
1. 两者的异同点
- 共同点:
- 继承自
AbstractStringBuilder,内部通过动态数组存储字符 - 提供
append()、insert()、delete()等修改方法,支持原地修改
- 继承自
- 核心区别:
StringBuffer:线程安全(方法加了synchronized锁),性能较低StringBuilder:非线程安全,性能更高(单线程首选)
2. 常用方法与性能对比
核心方法:
append(任意类型):末尾追加内容(最常用)insert(int offset, 任意类型):指定位置插入delete(int start, int end):删除 [start, end) 区间内容reverse():反转字符串toString():转为 String 类型
性能测试:
public class StringPerformance {
public static void main(String[] args) {
int loop = 100000; // 十万次拼接
// String拼接(效率极低)
long start1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < loop; i++) {
s += i;
}
long end1 = System.currentTimeMillis();
System.out.println("String耗时:" + (end1 - start1) + "ms"); // 约3000ms
// StringBuilder拼接(效率极高)
long start2 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < loop; i++) {
sb.append(i);
}
long end2 = System.currentTimeMillis();
System.out.println("StringBuilder耗时:" + (end2 - start2) + "ms"); // 约5ms
}
}
结论:字符串修改频繁时,优先使用StringBuilder(单线程)或StringBuffer(多线程)。
三、包装类:基本类型的对象化封装
Java 是面向对象语言,但 8 种基本数据类型不是对象。包装类的出现正是为了将基本类型封装为对象,满足泛型、集合等场景的需求。
1. 八大包装类对应关系
| 基本数据类型 | 包装类 | 父类 | 特殊说明 |
|---|---|---|---|
| byte | Byte | Number | - |
| short | Short | Number | - |
| int | Integer | Number | 最常用,缓存 - 128~127 区间对象 |
| long | Long | Number | - |
| float | Float | Number | - |
| double | Double | Number | - |
| char | Character | Object | 无父类 Number |
| boolean | Boolean | Object | 无父类 Number |
2. 核心功能与自动装箱拆箱
-
类型转换:
- 字符串转基本类型:
Integer.parseInt("123")、Double.parseDouble("3.14") - 基本类型转包装类:
Integer.valueOf(123)(推荐,利用缓存) - 包装类转基本类型:
Integer.intValue()
- 字符串转基本类型:
-
自动装箱与拆箱(JDK5+):
// 自动装箱:int -> Integer Integer a = 100; // 等价于 Integer a = Integer.valueOf(100); // 自动拆箱:Integer -> int int b = a; // 等价于 int b = a.intValue(); -
缓存机制:Integer 对
-128~127区间的值做了缓存,多次创建该区间的对象会复用:Integer x = 127; Integer y = 127; System.out.println(x == y); // true(复用缓存对象) Integer m = 128; Integer n = 128; System.out.println(m == n); // false(超出缓存范围,新建对象)
四、日期时间处理:从传统 API 到新特性
日期时间处理是开发中的难点,Java 提供了多套 API,其中 Java 8 的新 API 是目前的最佳选择。
1. 传统日期类(不推荐)
java.util.Date:表示特定瞬间,精度到毫秒,但多数方法已过时。SimpleDateFormat:用于日期格式化与解析,但线程不安全。
2. Java 8 新日期 API(推荐)
Java 8 引入的java.time包解决了传统 API 的线程安全、设计混乱等问题,核心类包括:
LocalDate:日期(年 / 月 / 日)LocalTime:时间(时 / 分 / 秒)LocalDateTime:日期 + 时间DateTimeFormatter:线程安全的格式化工具
核心优势:
- 不可变对象,线程安全
- 方法链编程,操作简洁
- 清晰区分日期、时间、带时区的时间
示例代码:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class NewDateDemo {
public static void main(String[] args) {
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间:" + now); // 2025-10-21T15:30:00.123
// 格式化(线程安全)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm");
String formatted = now.format(formatter);
System.out.println("格式化后:" + formatted); // 2025年10月21日 15:30
// 日期计算
LocalDateTime tomorrow = now.plusDays(1); // 明天
LocalDateTime lastMonth = now.minusMonths(1); // 上个月
System.out.println("明天同一时间:" + tomorrow.format(formatter));
// 解析字符串
LocalDateTime parsed = LocalDateTime.parse("2023年01月01日 08:00", formatter);
System.out.println("解析后的月份:" + parsed.getMonthValue()); // 1
}
}
总结
- 字符串选择:少量操作选
String,频繁修改选StringBuilder(单线程)或StringBuffer(多线程)。 - 包装类注意:利用自动装箱拆箱简化代码,但需注意
null拆箱的空指针风险和缓存机制的影响。 - 日期处理:彻底抛弃
Date和SimpleDateFormat,全面使用 Java 8 的java.time包,兼顾安全性与易用性。
掌握这些基础组件的特性与最佳实践,能显著提升代码质量与开发效率,避免常见的性能问题和 bug。
979

被折叠的 条评论
为什么被折叠?



