1. 概述
本教程将快速介绍 java.lang.System
类的核心功能与特性。作为 Java 基础库的关键成员,System 类提供了与 JVM 交互的底层能力。
2. IO 操作
System 类最核心的功能之一是提供标准 I/O 流的访问。它暴露了三个关键字段:
out
:标准输出流err
:标准错误流in
:标准输入流
2.1 System.out
System.out
指向标准输出流,封装为 PrintStream
类型,常用于控制台输出:
System.out.print("这是一行内联消息");
进阶用法是通过 System.setOut
重定向输出目标:
// 重定向到文本文件
System.setOut(new PrintStream("output.txt"));
2.2 System.err
System.err
与 System.out
类似,都是 PrintStream
实例,但专用于错误输出:
System.err.print("这是一行错误消息");
⚠️ 控制台通常会对错误流和输出流进行差异化渲染(如不同颜色)。更多细节可查阅 PrintStream 文档。
2.3 System.in
System.in
暴露标准输入流(InputStream
),用于读取控制台输入。基础用法稍显繁琐:
public String readUsername(int length) throws IOException {
byte[] name = new byte[length];
System.in.read(name, 0, length); // 默认从控制台读取
return new String(name);
}
踩坑提醒:用户输入的多余字节会残留在流中,等待下次读取!更优雅的方案是使用 BufferedReader
:
public String readUsername() throws IOException {
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));
return reader.readLine();
}
⚠️ 切勿关闭标准输入流!关闭后程序生命周期内将无法再次读取。进阶用法可通过 System.setIn
重定向输入源。
3. 实用工具方法
System 类提供大量实用方法,涵盖以下场景:
- 控制台访问
- 数组复制
- 时间观测
- 程序退出
- 运行时属性访问
- 环境变量访问
- 垃圾回收管理
3.1 访问控制台
Java 1.6 引入了比直接使用 System.out/in
更强大的控制台交互方式:
public String readUsername() {
Console console = System.console();
return console == null ? null :
console.readLine("%s", "请输入用户名: ");
}
⚠️ 必须检查空值!根据 JVM 启动方式(如 IDE 运行),console()
可能返回 null
。更多用法见 Console 文档。
3.2 数组复制
System.arraycopy
是 C 风格的数组复制方法,支持全量或部分复制:
int[] a = {34, 22, 44, 2, 55, 3};
int[] b = new int[a.length];
// 全量复制
System.arraycopy(a, 0, b, 0, a.length);
assertArrayEquals(a, b);
// 部分复制:从 a[1] 开始复制 2 个元素到 b[3]
System.arraycopy(a, 1, b, 3, 2);
assertArrayEquals(new int[] {0, 0, 0, 22, 44, 0}, b);
❌ 可能抛出异常:
NullPointerException
:任一数组为 nullIndexOutOfBoundsException
:越界访问ArrayStoreException
:类型不匹配
3.3 时间观测
System 提供两个时间相关方法:
currentTimeMillis
:返回 Unix 纪元(1970-01-01 00:00:00 UTC)至今的毫秒数 ```java public long nowPlusOneHour() { return System.currentTimeMillis() + 3600 * 1000L; }
public String nowPrettyPrinted() { return new Date(System.currentTimeMillis()).toString(); }
2. `nanoTime`:返回 JVM 启动后的纳秒级时间,适合测量时间间隔
```java
long startTime = System.nanoTime();
// 执行代码
long endTime = System.nanoTime();
assertTrue(endTime - startTime < 10000);
⚠️ 避免直接比较时间值!由于数值溢出风险,应使用差值比较(如 endTime - startTime < threshold
)。
3.4 程序退出
System.exit
可强制终止当前程序,需指定退出码:
if (error) {
System.exit(1); // 非零表示异常退出
} else {
System.exit(0); // 零表示正常退出
}
⚠️ 慎用此方法!在 Web 服务器等环境中调用可能导致整个应用崩溃。
3.5 访问运行时属性
通过 System.getProperty
访问 JVM 属性,支持动态管理:
// 获取属性
public String getJavaVMVendor() {
return System.getProperty("java.vm.vendor");
}
// 设置属性
System.setProperty("abckey", "abcvaluefoo");
assertEquals("abcvaluefoo", System.getProperty("abckey"));
// 清除属性
System.clearProperty("abckey");
assertNull(System.getProperty("abckey"));
✅ 支持默认值:
System.clearProperty("dbHost");
String host = System.getProperty("dbHost", "db.host.com");
assertEquals("db.host.com", host);
通过 System.getProperties()
获取所有属性:
Properties properties = System.getProperties();
properties.clear(); // 清空所有属性(危险操作!)
3.6 访问环境变量
System.getenv
提供只读的环境变量访问:
public String getPath() {
return System.getenv("PATH");
}
3.7 垃圾回收管理
System 提供两个垃圾回收相关方法(慎用):
System.runFinalization()
:建议 JVM 执行finalize()
方法System.gc()
:建议 JVM 执行垃圾回收
⚠️ 不保证立即执行!仅作为优化建议,典型场景如桌面应用最小化时触发:
public void windowStateChanged(WindowEvent event) {
if (event == WindowEvent.WINDOW_DEACTIVATED) {
System.gc(); // 触发垃圾回收(不保证执行)
}
}
更多细节见 Java finalize 指南。