在 Java 编程中,除了基本数据类型和面向对象编程的基础知识外,掌握 Java API 中提供的常用类库对于高效开发至关重要。这些类库封装了大量常用的功能,极大地简化了开发过程。
本章将介绍 Java 中一些最常用且基础的类,包括 String 类及其相关操作、StringBuilder 和 StringBuffer、Math 类、System 类,以及日期时间相关的 Date 类和 DateFormat。
1. String 类及其常用方法
String 类是 Java 中用于表示字符串的类,它位于 java.lang 包中。String 对象是不可变的(immutable),这意味着一旦创建,它的内容就不能被改变。每次对 String 对象进行修改操作(如拼接、替换)时,都会创建一个新的 String 对象。
1.1 String 对象的创建
有两种主要方式创建 String 对象:
-
直接赋值(字面量方式):
String s1 = "Hello"; String s2 = "Hello"; // s1 和 s2 引用的是字符串常量池中的同一个对象 System.out.println(s1 == s2); // true这种方式会优先在字符串常量池(String Pool)中查找是否存在相同内容的字符串。如果存在,则直接返回该字符串的引用;如果不存在,则在常量池中创建新的字符串对象并返回其引用。
-
使用
new关键字:String s3 = new String("World"); String s4 = new String("World"); // s3 和 s4 引用的是堆内存中不同的对象 System.out.println(s3 == s4); // false使用
new关键字会强制在堆内存中创建一个新的String对象,即使字符串常量池中已经存在相同内容的字符串。
1.2 String 的不可变性
String 的不可变性是其一个重要特性。例如:
String str = "Java";
str = str + " Programming"; // 实际上创建了一个新的字符串 "Java Programming"
System.out.println(str); // 输出: Java Programming
虽然看起来 str 的内容改变了,但实际上是 str 变量的引用指向了一个新的 String 对象,原来的 “Java” 对象并没有改变,只是没有被 str 引用而已。
不可变性带来了线程安全和字符串常量池的优化,但也可能导致在大量字符串拼接操作时性能下降(因为会创建大量中间对象)。
1.3 String 常用方法
String 类提供了丰富的方法来操作字符串,以下是一些最常用的方法:
1.3.1 获取信息
length(): 返回字符串的长度。String s = "hello"; System.out.println(s.length()); // 5isEmpty(): 判断字符串是否为空(长度为0)。String s = ""; System.out.println(s.isEmpty()); // truecharAt(int index): 返回指定索引处的字符。String s = "hello"; System.out.println(s.charAt(1)); // eindexOf(String str)/indexOf(String str, int fromIndex): 返回指定子字符串第一次出现的索引,如果不存在则返回 -1。可以指定从哪个索引开始查找。String s = "hello world"; System.out.println(s.indexOf("o")); // 4 System.out.println(s.indexOf("o", 5)); // 7 System.out.println(s.indexOf("xyz")); // -1lastIndexOf(String str)/lastIndexOf(String str, int fromIndex): 返回指定子字符串最后一次出现的索引。String s = "hello world"; System.out.println(s.lastIndexOf("o")); // 7
1.3.2 比较
equals(Object anObject): 比较两个字符串的内容是否相等。推荐使用此方法进行字符串内容比较。String s1 = "Hello"; String s2 = "Hello"; String s3 = new String("Hello"); System.out.println(s1.equals(s2)); // true System.out.println(s1.equals(s3)); // trueequalsIgnoreCase(String anotherString): 忽略大小写比较两个字符串的内容是否相等。String s1 = "Hello"; String s2 = "hello"; System.out.println(s1.equalsIgnoreCase(s2)); // truecompareTo(String anotherString): 按字典顺序比较两个字符串。如果当前字符串小于、等于或大于anotherString,则分别返回负整数、零或正整数。String s1 = "apple"; String s2 = "banana"; String s3 = "apple"; System.out.println(s1.compareTo(s2)); // 负数 System.out.println(s2.compareTo(s1)); // 正数 System.out.println(s1.compareTo(s3)); // 0startsWith(String prefix): 测试此字符串是否以指定的前缀开始。endsWith(String suffix): 测试此字符串是否以指定的后缀结束。String filename = "document.txt"; System.out.println(filename.startsWith("doc")); // true System.out.println(filename.endsWith(".txt")); // true
1.3.3 查找与替换
contains(CharSequence s): 判断字符串是否包含指定的字符序列。String s = "hello world"; System.out.println(s.contains("world")); // truereplace(char oldChar, char newChar): 返回一个新的字符串,它是通过用newChar替换此字符串中所有出现的oldChar得到的。replace(CharSequence target, CharSequence replacement): 替换所有匹配的字符序列。String s = "hello world"; System.out.println(s.replace('o', 'x')); // hellx wxrld System.out.println(s.replace("world", "Java")); // hello JavareplaceAll(String regex, String replacement): 使用给定的替换内容替换此字符串所有匹配给定的正则表达式的子字符串。replaceFirst(String regex, String replacement): 使用给定的替换内容替换此字符串第一个匹配给定的正则表达式的子字符串。String s = "Java is fun, Java is powerful."; System.out.println(s.replaceAll("Java", "Python")); // Python is fun, Python is powerful. System.out.println(s.replaceFirst("Java", "Python")); // Python is fun, Java is powerful.
1.3.4 截取与拼接
substring(int beginIndex): 返回一个新字符串,它是此字符串从beginIndex开始截取到末尾的子字符串。substring(int beginIndex, int endIndex): 返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex-1的子字符串。String s = "HelloWorld"; System.out.println(s.substring(5)); // World System.out.println(s.substring(0, 5)); // Helloconcat(String str): 将指定字符串连接到此字符串的末尾。等同于+运算符。String s1 = "Hello"; String s2 = "World"; System.out.println(s1.concat(s2)); // HelloWorld
1.3.5 大小写转换与去除空白
toLowerCase(): 将所有字符转换为小写。toUpperCase(): 将所有字符转换为大写。String s = "Hello World"; System.out.println(s.toLowerCase()); // hello world System.out.println(s.toUpperCase()); // HELLO WORLDtrim(): 返回一个字符串,其值为此字符串,并删除了前导和尾随的空白。String s = " Hello World "; System.out.println(s.trim()); // Hello World
1.3.6 转换为数组
toCharArray(): 将此字符串转换为新的字符数组。String s = "abc"; char[] chars = s.toCharArray(); // {'a', 'b', 'c'}split(String regex): 根据给定的正则表达式的匹配拆分此字符串。String s = "apple,banana,orange"; String[] fruits = s.split(","); // {"apple", "banana", "orange"}
1.3.7 格式化
format(String format, Object... args): 使用指定的格式字符串和参数返回一个格式化字符串。类似于 C 语言的sprintf。String name = "Alice"; int age = 30; String formattedString = String.format("Name: %s, Age: %d", name, age); System.out.println(formattedString); // Name: Alice, Age: 30
2. StringBuilder 与 StringBuffer
由于 String 对象的不可变性,当需要频繁修改字符串内容(如大量拼接操作)时,会创建大量的中间 String 对象,导致性能下降和内存浪费。为了解决这个问题,Java 提供了 StringBuilder 和 StringBuffer 类。
这两个类都表示可变的字符序列,它们提供了许多与 String 类似的方法,但操作是在原对象上进行的,不会创建新的对象。
2.1 StringBuilder
- 非线程安全:
StringBuilder的方法没有同步(synchronized)修饰,因此在单线程环境下性能更高。 - 推荐使用场景:在单线程环境下进行字符串的频繁修改和拼接操作。
常用方法:
append(String str): 追加字符串。insert(int offset, String str): 在指定位置插入字符串。delete(int start, int end): 删除指定范围的字符。reverse(): 反转字符序列。toString(): 将StringBuilder对象转换为String对象。
示例:
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
System.out.println(sb.toString()); // Hello World
sb.insert(6, "Java ");
System.out.println(sb.toString()); // Hello Java World
sb.delete(6, 11); // 删除 "Java "
System.out.println(sb.toString()); // Hello World
sb.reverse();
System.out.println(sb.toString()); // dlroW olleH
2.2 StringBuffer
- 线程安全:
StringBuffer的所有公共方法都经过同步处理(synchronized),因此在多线程环境下是安全的。 - 性能开销:由于同步机制,
StringBuffer的性能通常比StringBuilder稍低。 - 推荐使用场景:在多线程环境下进行字符串的频繁修改和拼接操作。
StringBuffer 的方法与 StringBuilder 基本相同。
示例:
StringBuffer sbuf = new StringBuffer();
sbuf.append("Hello").append(" ").append("Java");
System.out.println(sbuf.toString()); // Hello Java
2.3 String、StringBuilder、StringBuffer 总结
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 线程安全 | 非线程安全 | 线程安全 |
| 性能 | 拼接操作性能最低 | 拼接操作性能最高 | 拼接操作性能次之 |
| 使用场景 | 字符串内容不常改变 | 单线程下频繁字符串操作 | 多线程下频繁字符串操作 |
选择建议:
- 如果字符串内容不需要改变,或者改变次数很少,使用
String。 - 如果需要频繁修改字符串内容,且在单线程环境下,使用
StringBuilder。 - 如果需要频繁修改字符串内容,且在多线程环境下,使用
StringBuffer。
3. Math 类与 System 类
3.1 Math 类
Math 类位于 java.lang 包中,提供了执行基本数学运算的方法,如初等指数、对数、平方根和三角函数。Math 类中的所有方法都是 static 的,可以直接通过类名调用,无需创建对象。
常用方法:
abs(double a): 返回a的绝对值。ceil(double a): 返回大于或等于a的最小整数(向上取整)。floor(double a): 返回小于或等于a的最大整数(向下取整)。round(float a)/round(double a): 四舍五入到最接近的整数。max(double a, double b): 返回两个数中较大的一个。min(double a, double b): 返回两个数中较小的一个。pow(double base, double exponent): 返回base的exponent次幂。sqrt(double a): 返回a的平方根。random(): 返回一个[0.0, 1.0)范围内的随机double值。PI: 圆周率常量。E: 自然对数的底数常量。
示例:
public class MathDemo {
public static void main(String[] args) {
System.out.println("绝对值: " + Math.abs(-10)); // 10
System.out.println("向上取整: " + Math.ceil(4.1)); // 5.0
System.out.println("向下取整: " + Math.floor(4.9)); // 4.0
System.out.println("四舍五入: " + Math.round(4.5)); // 5
System.out.println("最大值: " + Math.max(10, 20)); // 20
System.out.println("最小值: " + Math.min(10, 20)); // 10
System.out.println("2的3次方: " + Math.pow(2, 3)); // 8.0
System.out.println("16的平方根: " + Math.sqrt(16)); // 4.0
System.out.println("随机数: " + Math.random()); // 0.0 到 1.0 之间
System.out.println("PI: " + Math.PI);
}
}
3.2 System 类
System 类位于 java.lang 包中,它包含了一些有用的类字段和方法。它不能被实例化,所有成员都是 static 的。System 类提供了标准输入、标准输出和错误输出流;访问外部定义的属性和环境变量;一种加载文件和库的方法;以及实用方法,用于快速复制数组的某一部分。
常用方法和字段:
out: 标准输出流,System.out.println()就是通过它实现的。in: 标准输入流。err: 标准错误输出流。currentTimeMillis(): 返回当前时间(以毫秒为单位)。常用于计算程序执行时间。exit(int status): 终止当前正在运行的 Java 虚拟机。参数status为非零值表示异常终止。arraycopy(Object src, int srcPos, Object dest, int destPos, int length): 从源数组复制一个数组到目标数组。gc(): 运行垃圾回收器。建议 JVM 尽快执行垃圾回收,但不保证立即执行。getProperty(String key): 获取指定系统属性的值。
示例:
import java.util.Arrays;
public class SystemDemo {
public static void main(String[] args) {
// 获取当前时间戳
long startTime = System.currentTimeMillis();
System.out.println("程序开始时间: " + startTime + " ms");
// 数组复制
int[] srcArray = {1, 2, 3, 4, 5};
int[] destArray = new int[5];
System.arraycopy(srcArray, 0, destArray, 0, srcArray.length);
System.out.println("复制后的数组: " + Arrays.toString(destArray));
// 获取系统属性
System.out.println("Java 版本: " + System.getProperty("java.version"));
System.out.println("操作系统: " + System.getProperty("os.name"));
// 模拟一些操作
for (int i = 0; i < 100000; i++) {
String s = "test" + i;
}
long endTime = System.currentTimeMillis();
System.out.println("程序结束时间: " + endTime + " ms");
System.out.println("程序执行耗时: " + (endTime - startTime) + " ms");
// 退出程序
// System.exit(0); // 正常退出
// System.out.println("这行代码不会被执行");
}
}
4. Date 类与 DateFormat
在 Java 中处理日期和时间,早期主要使用 java.util.Date 类和 java.text.DateFormat(或其子类 SimpleDateFormat)。虽然 Java 8 引入了新的日期时间 API (java.time 包),但了解旧的 API 仍然很重要,因为很多遗留代码和库还在使用它们。
4.1 Date 类
java.util.Date 类表示特定的瞬间,精确到毫秒。它的大部分构造方法和方法都已过时,推荐使用 Calendar 类或 Java 8 的日期时间 API。
常用方法:
Date(): 分配Date对象并对其进行初始化,使其表示分配它的时间(精确到毫秒)。getTime(): 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此Date对象表示的毫秒数。setTime(long time): 设置此Date对象,以表示time参数的毫秒数。
示例:
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
// 创建一个表示当前时间的 Date 对象
Date currentDate = new Date();
System.out.println("当前日期和时间: " + currentDate); // 输出格式类似: Thu Jan 01 08:00:00 CST 1970
// 获取时间戳(毫秒)
long timestamp = currentDate.getTime();
System.out.println("当前时间戳 (毫秒): " + timestamp);
// 根据时间戳创建 Date 对象
Date specificDate = new Date(1678886400000L); // 2023-03-15 00:00:00 GMT
System.out.println("特定日期: " + specificDate);
// 比较日期 (不推荐直接使用,推荐使用 getTime() 或 Calendar)
Date anotherDate = new Date();
System.out.println("当前日期是否在另一个日期之后: " + currentDate.after(anotherDate));
System.out.println("当前日期是否在另一个日期之前: " + currentDate.before(anotherDate));
System.out.println("两个日期是否相等: " + currentDate.equals(anotherDate));
}
}
4.2 DateFormat 与 SimpleDateFormat
DateFormat 是一个抽象类,用于将日期/时间格式化为字符串,或将字符串解析为日期/时间。它的常用子类是 SimpleDateFormat。
SimpleDateFormat 是一个具体的类,用于以各种格式解析和格式化日期。它允许你通过模式字符串来定义日期时间的显示格式。
模式字母:
| 字母 | 日期或时间元素 | 表示 | 示例 |
|---|---|---|---|
y | 年 | Year | yyyy (2023) |
M | 月 | Month | MM (03), MMM (Mar) |
d | 日 | Day | dd (15) |
H | 小时 (0-23) | Hour | HH (14) |
h | 小时 (1-12) | Hour | hh (02) |
m | 分 | Minute | mm (30) |
s | 秒 | Second | ss (59) |
S | 毫秒 | Millisecond | SSS (999) |
E | 星期几 | Day of week | E (Wed), EEEE (Wednesday) |
a | 上午/下午 | Am/pm | a (AM/PM) |
常用方法:
format(Date date): 将Date对象格式化为日期/时间字符串。parse(String source): 将给定字符串的文本解析为Date。
示例:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
Date now = new Date();
// 1. 日期格式化 (Date -> String)
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate1 = formatter1.format(now);
System.out.println("格式化1: " + formattedDate1); // 2023-10-26 14:30:00
SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss a");
String formattedDate2 = formatter2.format(now);
System.out.println("格式化2: " + formattedDate2); // 2023年10月26日 星期四 14:30:00 下午
// 2. 字符串解析 (String -> Date)
String dateString = "2023-08-08 10:20:30";
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date parsedDate = parser.parse(dateString);
System.out.println("解析后的日期: " + parsedDate);
} catch (ParseException e) {
System.out.println("日期解析失败: " + e.getMessage());
}
// 注意:SimpleDateFormat 是非线程安全的,在多线程环境下需要注意
// 推荐在多线程环境下为每个线程创建独立的 SimpleDateFormat 实例,或者使用 ThreadLocal
}
}
本章我们学习了 Java 中一些基础但非常重要的常用类,包括 String 及其不可变性、StringBuilder 和 StringBuffer 在字符串操作中的应用、Math 类的数学运算、System 类的系统级操作,以及 Date 和 SimpleDateFormat 进行日期时间处理。掌握这些类是进行 Java 开发的基础。在下一章中,我们将继续学习 Java 中的其他常用类。
&spm=1001.2101.3001.5002&articleId=149727139&d=1&t=3&u=91713b7d12b44752af93b4a9b9b00663)

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



