system包装类的可维护性关键在于遵循标准异常处理原则:明确行为边界、精准表达错误、分层职责清晰;只抛出系统层异常,不混入业务逻辑,原样或链式包装原始异常,提供语义化静态工具方法,并确保自定义异常可序列化且携带上下文。

让 System 包装类具备可维护性,关键不是“加 try-catch”,而是用标准异常处理原则约束它的行为边界、错误表达和分层职责。System 类通常封装底层系统调用(如时间、环境变量、标准输入输出、安全策略等),一旦出错,必须清晰暴露“哪里错了、为什么错、是否可恢复”,否则上层代码会陷入盲目重试或静默失败。
明确区分系统异常与业务异常
System 包装类只应抛出真正属于系统层的问题,比如:
• SecurityException:调用 System.setSecurityManager 时被策略拒绝
• UnsupportedOperationException:在不支持的运行时环境中调用 System.console()
• NullPointerException(仅当传入 null 参数且 API 明确禁止)
不要把业务判断塞进 System 层——例如“读取配置失败”不该由 System.getProperty 抛出自定义 BizConfigException,那是上层 ConfigService 的责任。System 层只负责如实反映 JVM 或 OS 的反馈。
避免吞掉原始异常或模糊化错误类型
常见反模式:
• 在包装方法里 catch (Exception e) { return null; } —— 调用方完全无法感知失败
• 将 SecurityException 包装成 RuntimeException 并抹去 stack trace —— 安全审计时丢失上下文
正确做法:
• 原样抛出受检异常(如 SecurityException 是受检的,不可擅自转为非受检)
• 若需增强信息,用构造函数链式包装:new SecurityException("Failed to set property 'x', reason: " + e.getMessage(), e)
• 所有日志记录必须带原始异常对象,不能只记 message
用静态工具方法封装常见失败场景
System 类本身是 final、无实例状态的,适合提供语义明确的静态辅助方法,例如:
• SystemEnv.getRequiredProperty(String key):找不到时抛出 IllegalArgumentException(带 key 名),而非返回 null
• SystemClock.nowUtc():内部捕获 SecurityException 并转为 IllegalStateException(说明“当前环境禁止访问系统时钟”,属不可恢复故障)
• SystemIo.readStdinLine():对 IOException 统一封装为 unchecked 的 SystemIoException,并保留 cause
确保所有自定义异常可序列化且携带上下文
如果包装类引入了自定义异常(如 SystemIoException),必须:
• 显式声明 serialVersionUID(集群或远程调用场景下反序列化必需)
• 构造函数接收关键参数(如 propertyKey、fileName、timeoutMs)并存为 final 字段,不依赖 getMessage() 拼接
• 继承选择合理:需要强制调用方处理的 → extends Exception;纯系统故障 → extends RuntimeException
这样,当异常跨层传播或被日志框架捕获时,关键定位信息不会丢失。










