在调用超级构造函数时尝试使用资源

时间:2016-06-07 07:36:46

标签: java java-8 try-with-resources

在构造函数中打开InputStream然后将其传递给超级构造函数时,是否有使用try-with-resources的好方法?

基本上我想做的是:

public class A {
    public A(InputStream stream) {
        // Do something with the stream but don't close it since we didn't open it
    }
}

public class B {
    public B(File file) {
        // We open the stream so we need to ensure it's properly closed
        try (FileInputStream stream = new FileInputStream(file)) {
            super(new FileInputStream(file));
        }
    }
}

但是,当然,因为super必须是构造函数中的第一个语句,所以这是不允许的。有没有什么好办法实现这个目标?

3 个答案:

答案 0 :(得分:25)

考虑使用静态工厂方法而不是直接使用构造函数。至少将B的构造函数设为私有,并创建一个方法,如

private B(InputStream is) {
    super(is);
    // Whatever else is needed
}

public static B newInstance(File file) {
    B result;
    try (FileInputStream stream = new FileInputStream(file)) {
        result = new B(stream);
    }
    // Further processing
    return result;
}

答案 1 :(得分:2)

另一种方法:

public class A {
    protected A(){
        // so he can't be called from the outside, subclass ensure that init is done properly.
    }

    public A(InputStream stream) {
        init(stream);
    }
    // not be able to call it from outside
    protected final init(InputStream is){
        //here goes the code
    }
}

public class B {
    public B(File file) {
        // We open the stream so we need to ensure it's properly closed
        try (FileInputStream stream = new FileInputStream(file)) {
            init(stream);
        }
    }
}

我在这里发布这个可能的答案,但是我在这里问:

  1. 您可以更新A&#39的代码
  2. 您正在将构造函数的代码移动到init方法,这要归功于受保护的空arg构造函数,只有子类必须正确处理对init的调用。有些人可能会认为设计不太好。我的观点是,一旦你继承了一些东西,你只需要在使用它时就必须了解它。

答案 2 :(得分:-1)

可悲的是,我手边没有编译器可以测试,但是你不能这样做。

public class B {
    private static InputStream file2stream(File f){
        // We open the stream so we need to ensure it's properly closed
        try (FileInputStream stream = new FileInputStream(file)) {
            return stream;
        }catch(/*what you need to catch*/){
             //cleanup
             // possibly throw runtime exception
        }
    }
    public B(File file) {
        super(file2stream(file))
    }
}