Try-with-resources при вызове супер-конструктора
Есть ли хороший способ использовать 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 properly closed
try (FileInputStream stream = new FileInputStream(file)) {
super(new FileInputStream(file));
}
}
}
Но, конечно, поскольку super
должен быть первым утверждением в конструкторе, это недопустимо. Есть ли хороший способ достичь этого?
Ответы
Ответ 1
Рассмотрите возможность использования статического метода factory вместо прямого использования конструктора. Создайте как минимум B
конструктор private и создайте такой метод, как
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 properly closed
try (FileInputStream stream = new FileInputStream(file)) {
init(stream);
}
}
}
Я размещаю это здесь как возможный ответ, однако здесь я замираю:
- Вы можете обновить код
- Вы перемещаете код конструктора в метод init, благодаря защищенному пустому конструктору arg, только подклассы должны обрабатывать вызов для инициализации должным образом. Некоторые могут видеть, что это не так хорошо спроектировано. Моя точка зрения заключается в том, что как только вы подклассифицируете что-то, вам нужно больше узнать об этом, просто когда вы просто используете его.
Ответ 3
К сожалению, у меня нет компилятора для проверки, но вы не могли бы сделать следующее.
public class B {
private static InputStream file2stream(File f){
// We open the stream so we need to ensure it 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))
}
}