1. 方法定义

System.err 是 Java System 类中的静态成员变量,类型为 PrintStream

public final class System {
    public static final PrintStream err;
}

2. 功能说明

  • 标准错误流:专用于输出错误信息、警告和调试消息。
  • 默认目标:与控制台(Console)关联(通常为红色文本)。
  • 即时性:默认无缓冲,输出立即生效(与 System.out 的缓冲不同)。
  • 独立性:与标准输出流 System.out 分离,可分别重定向。

3. 示例代码

public class SystemErrExample {
    public static void main(String[] args) {
        // 基础错误输出
        System.err.println("错误: 文件未找到!");

        // 异常处理
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.err.println("算术异常: " + e.getMessage());
        }

        // 重定向错误流到文件
        try (PrintStream fileErr = new PrintStream("error.log")) {
            System.setErr(fileErr); // 重定向
            System.err.println("此错误将写入文件");
        } catch (FileNotFoundException e) {
            System.err.println("重定向失败: " + e);
        }
    }
}

4. 使用技巧

  • 快速调试:临时插入 System.err.println("DEBUG: value=" + value); 定位问题。
  • 高亮关键信息:在控制台中用红色文本突出显示错误。
  • 与日志框架集成:重定向到日志文件(如 SLF4J):
    System.setErr(new PrintStream(new LoggingOutputStream(LoggerFactory.getLogger("STDERR"))));
    

5. 常见错误

  1. 混淆 outerr

    System.out.println("正常消息");  // 应使用 System.out
    System.err.println("错误消息");  // 应使用 System.err
    
    • 后果:日志中错误与正常输出混合,难以区分。
  2. 未处理重定向的关闭

    PrintStream ps = new PrintStream("error.log");
    System.setErr(ps);
    // 忘记 ps.close() 会导致资源泄露!
    
    • 修复:使用 try-with-resources 自动关闭。
  3. 性能敏感场景滥用

    for (int i = 0; i < 100000; i++) {
        System.err.println("低效循环输出"); // 频繁 I/O 操作
    }
    
    • 后果:严重性能下降。

6. 注意事项

  • 线程安全PrintStream 方法使用 synchronized,多线程安全。
  • 重定向影响范围System.setErr() 影响整个 JVM 的错误流。
  • 关闭风险不要关闭原始 System.err(调用 System.err.close() 会使后续错误输出失败)。

7. 最佳实践与性能优化

  • 生产环境替代方案
    使用日志框架(Log4j/SLF4J)代替 System.err,支持级别过滤和异步输出。

    Logger logger = LoggerFactory.getLogger(getClass());
    logger.error("错误详情", exception);
    
  • 条件输出:通过调试开关控制输出:

    private static final boolean DEBUG = true;
    if (DEBUG) {
        System.err.println("[DEBUG] 状态检查: " + state);
    }
    
  • 缓冲优化:高频输出时启用缓冲(需手动刷新):

    PrintStream bufferedErr = new PrintStream(
        new BufferedOutputStream(new FileOutputStream("errors.log")), true);
    System.setErr(bufferedErr);
    
  • 重定向恢复:保存原始流以便恢复:

    PrintStream originalErr = System.err;
    // ...重定向操作...
    System.setErr(originalErr); // 恢复
    

8. 总结

关键点 说明
用途 专用于错误、警告和调试信息的输出
与 System.out 区别 无缓冲、独立重定向、语义区分(错误 vs 正常)
适用场景 命令行工具、简单调试、临时错误报告
生产环境建议 替换为日志框架(Log4j/SLF4J)以获得异步、分级和结构化日志
性能关键点 避免高频循环中使用;需重定向时用缓冲流
线程安全 是(内部同步)

行动指南

  1. 开发调试阶段:用 System.err 快速输出关键错误。
  2. 生产环境:集成日志框架,重定向 System.err 到日志文件。
  3. 避免:在循环/高性能代码中直接使用,关闭原始流,混淆 outerr

核心原则System.err 是简单场景的利器,但复杂系统需升级到专业日志工具,平衡即时性与性能。