使用显式构造函数调用时如何避免“Potential resource leak”警告
方案1(最推荐):使用静态工厂方法替代构造函数重载
完全规避构造函数中this()必须是第一条语句的限制,同时从根源避免资源泄漏,是Java编码规范中推荐的处理方式。
public class MyClass implements AutoCloseable { private final InputStream input; // 构造函数私有化,仅内部调用 private MyClass(InputStream input) { this.input = input; // 执行实际初始化逻辑 } // 接收文件名的静态工厂方法 public static MyClass fromFileName(String filename) throws IOException { FileInputStream fis = new FileInputStream(filename); try { return new MyClass(fis); } catch (Exception initException) { // 构造过程出现异常,先关闭已打开的流再抛出异常 fis.close(); throw initException; } } // 直接接收输入流的静态工厂方法 public static MyClass fromInputStream(InputStream input) { return new MyClass(input); } // 类实例自身管理流的生命周期 @Override public void close() throws IOException { input.close(); } }
使用时直接把MyClass实例纳入try-with-resources管理即可:
try (MyClass instance = MyClass.fromFileName("test.txt")) { // 执行业务逻辑 } // 流会随MyClass实例自动关闭
方案2:保留构造函数写法,明确资源所有权
如果一定要保留原有多构造函数的写法,可以通过明确资源归属 + 注解忽略警告的方式处理:
- 让MyClass实现
AutoCloseable接口,在close方法中关闭持有的InputStream - 在类的Javadoc中明确标注:所有传入MyClass构造函数的InputStream将由当前实例负责关闭,外部调用方无需再手动关闭该资源
- 给字符串参数的构造函数添加
@SuppressWarnings("resource")注解,消除Eclipse的警告
代码示例:
public class MyClass implements AutoCloseable { private final InputStream input; public MyClass(InputStream input) { this.input = input; // 执行实际初始化逻辑 } @SuppressWarnings("resource") public MyClass(String filename) throws IOException { this(new FileInputStream(filename)); } @Override public void close() throws IOException { input.close(); } }
方案3:构造内完成全部读取逻辑
如果MyClass不需要长期持有输入流,仅需要在构造时读取文件内容完成初始化,可以直接在字符串参数的构造函数内完成文件读取、流关闭的全流程,不需要委托给另一个构造函数,自然不存在资源泄漏问题。
内容的提问来源于stack exchange,提问作者MRA
相关产品推荐
相关产品推荐

