Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Try-with-resources when calling super constructor

Tags:

Is there any good way of using try-with-resources when opening an InputStream in a constructor and then passing that to a super constructor?

Basically what I want to do is this:

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));         }     } } 

But, of course, since super must be the first statement in the constructor this isn't allowed. Is there any good way of achieving this?

like image 877
Raniz Avatar asked Jun 07 '16 07:06

Raniz


People also ask

Does try with resources need catch or finally?

Note: A try -with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try -with-resources statement, any catch or finally block is run after the resources declared have been closed.

Can you explain about try with resources?

In Java, the Try-with-resources statement is a try statement that declares one or more resources in it. A resource is an object that must be closed once your program is done using it. For example, a File resource or a Socket connection resource.

Can we use try with resources without catch?

If the exception throws from both try and finally blocks, the exception from try block will be suppressed with try-and-catch. On the other hand, if you use the try-with-resources statement, the exception from finally block (auto close throws exception) will be suppressed.

How do you write to try with resources?

A resource is an object to be closed at the end of the program. As seen from the above syntax, we declare the try-with-resources statement by, declaring and instantiating the resource within the try clause. specifying and handling all exceptions that might be thrown while closing the resource.


2 Answers

Consider using a static factory method instead of using the constructor directly. Make at least B's constructor private, and create a method such as

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; } 
like image 187
RealSkeptic Avatar answered Nov 12 '22 08:11

RealSkeptic


Another way to go :

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);         }     } } 

I'm posting this here as a possible answer, however here i'm consdering :

  1. You can update A's code
  2. You're moving constructor's code to an init method, thanks to protected empty arg constructor, only subclasses have to handle the call to init properly. Some may see that as not so well designed. My point is as soon your subclassing something, you have to know more about it that just when you just using it.
like image 28
Walfrat Avatar answered Nov 12 '22 08:11

Walfrat