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

2022-09-02 03:54:58

在构造函数中打开一个,然后将其传递给超级构造函数时,有什么好方法可以使用 try-with-resources 吗?InputStream

基本上我想做的是这样的:

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


答案 1

请考虑使用静态工厂方法,而不是直接使用构造函数。至少将 的构造函数设为私有,并创建一个方法,例如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;
}

答案 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的代码
  2. 您将构造函数的代码移动到 init 方法,这要归功于受保护的空 arg 构造函数,只有子类必须正确处理 init 调用。有些人可能会认为这设计得不太好。我的观点是,一旦你对某些东西进行了子类化,你就必须更多地了解它,而只是在你使用它的时候。

推荐