Correct use of Java exceptions - java

I have several questions about best use of exceptions in Java.
Consider the code below:
private String doHttpGetRequest(String url) throws IOException {
...
}
private Photo processJson(String json) throws JSON Exception{
...
}
private Photo getPhoto() throws IOException, JSON Exception {
String url = "http://...";
String response = doHttpGetRequest(url);
Photo photo = processJson(response);
photo.downloadImage();
return photo;
}
public static void main(String args[]) {
Photo p = null;
try {
p = getPhoto();
} catch( JSONException j ) {
// Re-try a few times, then display user alert
} catch( IOException e ) {
// Re-try a few times, then display user alert
}
if( p!=null)
// now display photo
}
This code is for an android app where the connection may not be very reliable, so I would like to re-try the getPhoto() method a few times to see if it will work, then fail and alert the user.
My questions:
I am opening an InputStream in doHttpGetRequest() and that method is throwing an IOException. How do I close the InputStream if it has thrown the exception? Without a finally block within the method that would allow me to close resources, i'm confused.
In main(), I'm only interested in whether getPhoto() works or does not work. Would I be better to surround statements inside getPhoto() with a try/catch block and catch the JSONException, throwing a new IOException when it is caught? This would lead to only having to catch one kind of exception in main(), leading to simpler code and not having duplicate functionality.
If p.getPhoto() throws an exception, I want to re-try it (possibly twice) and then display a user alert if this fails. Is there a common programming structure to doing this?

doHttpGetRequest() should be in charge of closing the inputstream. Finally-block there would be suitable for closing (why don't you want finally block?).
Do you have to pass any exceptions to the main method. You could surround doHttpGetRequest(url) with try{} and surround processJson with another (I quess this one doesn't benefit from retries). This would make the main() method cleaner.
If you go with my suggestion on 2. you could do the retrying like this:
String response = null;
for (int i = 0; i < RETRY_COUNT && response == null; i++){
try {
response = doHttpGetRequest(url);
} catch (IOException e){
// Possibly log the error here
}
}
if (response == null) return null;
EDIT: Bugfix

You can catch the exception, clean up and re-throw it. Why are you avoiding using finally block? It looks like it would fit there very well.
It will probably be more code than handling those two exception separately.
Put it in a for loop, continue if there was an exception and break if not.

You should still use try-finally block so you are able to close the resources. The block is used like this:
InputStream is;
try {
is = openStream(); //This is a sample code, which
//Do something with the stream
} finally {
if (is != null) is.close();
}
This way if an exception is thrown, the stream will be closed anyway, and the exception will be handled elsewhere.
I suggest you creating your own exception (say, PhotoReadingException) and throw it from getPhoto(), but setting its cause to the original exception via the initCause(Throwable cause) method.
Certainly, you can use a loop and a variable which shows if the operation was successful.
Photo p = null;
Exception ex = null;
for (int tries = 0; tries < MAX_TRIES; tries++) {
try {
p = getPhoto();
break;
} catch (PhotoReadingException photoException) {
ex = photoException;
}
}
if (ex != null) reportException(ex);

Related

Apparently missing an exception

in my android app I have an AsyncTask which downloads photos from my server. If I get an exception (mainly for connection time out) I show the user a message. My problem is that my code works MOST of the times, (meaning there are times when I interrupt the WiFi connection that I get an exception shown in my logcat but the message won't appear so I ended it up thinking that there might be an exception that I don't handle ) and I can't figure out the exact reason. I'll post the code run in my AsyncTask and the function that does the essential work. Hope you spot out something I'missing
#Override
protected String doInBackground(String... args) {
JSONParser jParser = new JSONParser();
JSONObject jsonObj = jParser.getJSONFromUrl(url);
Log.d("check1",url);
try {
list.addAll(processJsonData(jsonObj));
} catch (JSONException e) {
e.printStackTrace();
onDownloadFailed(this);
return "failed";
} catch (SocketException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
} catch (IOException e) {
Log.e("Exception", e.getLocalizedMessage());
onDownloadFailed(this);
return "failed";
}finally {
jsonObj=null;
}
return "done";
}
process JsonData is actually bigger that's the part for downloading the photos, the other part is about mapping string to an large Json File
private ArrayList<Monument> processJsonData(JSONObject jsonObj) throws IOException, SocketException, JSONException{
if(attachments!=null){
int lengthSize;
if(attachments.length()<3)
lengthSize=attachments.length();
else
lengthSize=3;
for(int j=0;j<lengthSize;++j){
JSONObject atta = attachments.getJSONObject(j);
JSONObject images = atta.optJSONObject(TAG_IMAGES);
if(images!=null){
JSONObject medium = images.getJSONObject(TAG_MEDIUM);
String url_image = medium.getString(TAG_URL_IMAGE);
String id = atta.getString("id");
String filename =title.replace(" ","")+id+".nomedia";
File destination = new File(MyApplication.getPhotoStorage() ,filename);
URL url = new URL (url_image);
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(destination);
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
localPhotosUrl.add(destination.getAbsolutePath());
}
}
}
Maybe you could name the actual exception that is beeing thrown?
It might be a RuntimeException and therefore unchecked.
For further information about checked/unchecked exceptions see: Oracle Docs - Exceptions
The API for InteruptedException says the following;
Thrown when a thread is waiting, sleeping, or otherwise occupied, and
the thread is interrupted, either before or during the activity.
Occasionally a method may wish to test whether the current thread has
been interrupted, and if so, to immediately throw this exception.
As described in the comments of the question, cancelling your AsyncTask only after checking that it has finished should prevent this issue.
Alternatively (but I would recommend against it), you could catch the InteruptedException in the method that cancels your AsyncTask to define your custom catch behavior there. Using catch to work around program logic flaws should only really be a last resort after reconsidering the logical flow of your code.

Assistance in writing my file writer method for a servlet

I have a simple servlet where I write to a file if it has a queryparameter 'hello', and since this is a test I want to display the error the the webpage also.
IntelliJ is complaining that I am not catching the IOException, not sure what's wrong:
private static void WriteToFile(String filePath, String fileName, String fileData) {
FileWriter writer = null;
try {
writer = new FileWriter(fileName);
writer.write(fileData);
} catch(IOException ex) {
} finally {
if(writer != null) {
writer.close();
}
}
}
Also, in my exception, I noticed on the web most people write:
How can I output the error to the web page?
You're not catching IOException when you call writer.close(); in the finally block.
You're also completely swallowing any IOException thrown in the main code, which is a really bad idea. If something's goes wrong, you'll have no idea what's happening.
I would personally suggest that you let that method throw the exception to the caller:
private static void writeToFile(String filePath, String fileName,
String fileData) throws IOException {
FileWriter writer = new FileWriter(fileName);
try {
writer.write(fileData);
} finally {
writer.close();
}
}
Note that if the try block throws an exception and the finally block does, you'll effectively "lose" the original exception. You may want to suppress exceptions throw when closing.
Or just use Guava which makes all of this simpler anyway with its Files class.
Or if you're using Java 7, you could use a try-with-resources statement.
(I note that you're ignoring filePath by the way - why?)
You can write in catch block too : writer.write(errorMessage);
or you may redirect to Error page if error occured

Throwing exceptions at the correct time

Just came across a rather confusing exam question, and my lecturer is away on holidays, so I come to StackOverflow begging for help!
The question is as follows :
"Joe has his own JoeConnection class for making connections between his computer and other computers. The class provides the following constructor and instance methods :
JoeConnection( String address ): Make a connection with the URL address.
void writeLn( String text ) : Write text to the JoeConnection.
String readLn( ): Read a line of text from the JoeConnection.
void clode( ) : Close the JoeConnection.
Joe's connections regularly fail and this causes errors. Using proper exception handling, demonstrate how to use Joe's JoeConnection class to
make a JoeConnection with the URL http://students.chat.box
write "Hello world" to the JoeConnection
read in a string from the JoeConnection
close the connection.
The connection handling should provide as man details as possible about the cause of failure and print the stack trace which led to the failure.
I have no idea how to tackle this, but I assume it is something similar to this :
public class Test {
try {
JoeConnection connection = new JoeConnection(http://students.chat.box);
} catch {
connectionError e; printStacktrace();}
}
}
Can anyone please help me figure this out? Thanks a lot.
Without an indication of what exceptions are thrown and why, the only proper exception handling is no handling at all. Don't catch an exception if you don't know how to fix the problem that triggered it.
But the further instructions in your assignment introduce a different notion of "proper." You're supposed to print a stack trace. So catch the exception and print a stack trace. You were on the right track, but your syntax was wrong. Refer back to your textbook and lecture notes to remind yourself what the syntax is for catching exceptions (and for passing strings to functions, for that matter).
try {
JoeConnection connection = new JoeConnection("http://students.chat.box");
connection.writeLn("Hello world");
// etc
} catch (Exception e) {
e.printStackTrace();
}
"Proper exception handling" is a little vague. I agree with #Rob Kennedy's statement that no exception handling is appropriate unless you know why the exception is thrown and what should be done with it. Otherwise, the exception should be allowed to propagate. So, for example:
void foo(String address) throws JoeException {
JoeConnection connection = new JoeConnection(address);
try {
connection.writeLn("Hello World!");
} finally {
// Ensure the connection is closed when finished.
// This happens whether an exception occurs or not.
connection.close();
}
}
If you wanted to catch the exception just to print it, you could do something like this:
void foo(String address) throws JoeException {
try {
JoeConnection connection = new JoeConnection(address);
try {
connection.writeLn("Hello World!");
} finally {
connection.close();
}
} catch (JoeException e) {
e.printStackTrace();
// Don't know what to do about this; rethrow.
throw e;
}
}
There is a subtlety here that even experience Java programmers can miss, though. If an exception occurs while creating the connection, it doesn't need to be closed. If an exception occurs while writing to the connection, it does need to be closed; thus the finally clause. However, the act of closing can also throw an exception. If closing the connection throws an exception, only that exception will be thrown by the try statement. If the finally clause was reached as a result of the writeLn operation throwing an exception, the exception of the writeLn call will be effectively ignored. This is probably not what you want.
Instead, we can try something ugly like this:
void foo(String address) throws JoeException {
try {
JoeConnection connection = new JoeConnection(address);
boolean normalCompletion = false;
try {
connection.writeLn("Hello World!");
normalCompletion = true;
} finally {
if (normalCompletion) {
// The writeLn operation completed normally.
// Propagate an exception thrown by the close operation.
connection.close();
} else {
// The writeLn operation completed abruptly.
// Ignore an exception thrown by the close operation.
try {
connection.close();
} catch (JoeException e) {
/* empty */
}
}
}
} catch (JoeException e) {
e.printStackTrace();
// Don't know what to do about this; rethrow.
throw e;
}
}
This looks (and is) syntactically hideous, but it does show "proper" exception handling of a sort. The language enhancement from Project Coin should clean this up a bit.
For starters, I can help you out with the syntax of what you wrote:
try {
JoeConnection connection = new JoeConnection("http://students.chat.box");
}
catch (JoeConnectionException e) {
e.printStacktrace();
}
I took the liberty of changing the linebreaks and renaming 'connectionError' as JoeConnectionException which looks more conventional to me.
You'll have to do something similar for the readLn, writeLn, and close method calls since it said that the connection regularly fails (i.e. not just while connecting).
Cheers, good luck.
Catching an exception should look like:
try {
JoeConnection conn = new JoeConnection(url);
} catch (YourExceptionClassNameHere e) {
e.printStackTrace();
}
Also: if you want to use a literal String, make sure you include the quotations. (It should be "http://students.chat.box".)
It's good to have a finally as well:
public class Test {
try {
JoeConnection connection = new JoeConnection(http://students.chat.box);
}
catch(Exception e) {
e.printStacktrace();
}
finally {
if(connection != null) {
connection.close();
}
}
}
Typically you handle exceptions if you know what to do with them (this involves error-recovery logic or wrapping an exception and throwing it to a higher level).
Assuming that each method throws an exception, you could do something like this for "maximum detail":
public class Test {
JoeConnection connection = null;
try {
connection = new JoeConnection("http://students.chat.box");
...
...
}
catch(OpenException e) {
System.out.println("Error while opening connection");
e.printStacktrace();
}
catch(WriteException e) {
System.out.println("Error while writing to connection");
e.printStacktrace();
}
catch(ReadException e) {
System.out.println("Error while reading from connection");
e.printStacktrace();
}
finally {
if(connection != null) {
connection.close();
}
}
}

throws Exception in finally blocks

Is there an elegant way to handle exceptions that are thrown in finally block?
For example:
try {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
finally {
try{
resource.close();
}
catch( Exception ex ) {
// Could not close the resource?
}
}
How do you avoid the try/catch in the finally block?
I usually do it like this:
try {
// Use the resource.
} catch( Exception ex ) {
// Problem with the resource.
} finally {
// Put away the resource.
closeQuietly( resource );
}
Elsewhere:
protected void closeQuietly( Resource resource ) {
try {
if (resource != null) {
resource.close();
}
} catch( Exception ex ) {
log( "Exception during Resource.close()", ex );
}
}
I typically use one of the closeQuietly methods in org.apache.commons.io.IOUtils:
public static void closeQuietly(OutputStream output) {
try {
if (output != null) {
output.close();
}
} catch (IOException ioe) {
// ignore
}
}
If you're using Java 7, and resource implements AutoClosable, you can do this (using InputStream as an example):
try (InputStream resource = getInputStream()) {
// Use the resource.
}
catch( Exception ex ) {
// Problem with the resource.
}
Arguably a bit over the top, but maybe useful if you're letting exceptions bubble up and you can't log anything from within your method (e.g. because it's a library and you'd rather let the calling code handle exceptions and logging):
Resource resource = null;
boolean isSuccess = false;
try {
resource = Resource.create();
resource.use();
// Following line will only run if nothing above threw an exception.
isSuccess = true;
} finally {
if (resource != null) {
if (isSuccess) {
// let close throw the exception so it isn't swallowed.
resource.close();
} else {
try {
resource.close();
} catch (ResourceException ignore) {
// Just swallow this one because you don't want it
// to replace the one that came first (thrown above).
}
}
}
}
UPDATE: I looked into this a bit more and found a great blog post from someone who has clearly thought about this more than me: http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html He goes one step further and combines the two exceptions into one, which I could see being useful in some cases.
As of Java 7 you no longer need to explicitly close resources in a finally block instead you can use try-with-resources syntax. The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
Assume the following code:
try( Connection con = null;
Statement stmt = con.createStatement();
Result rs= stmt.executeQuery(QUERY);)
{
count = rs.getInt(1);
}
If any exception happens the close method will be called on each of these three resources in opposite order in which they were created. It means the close method would be called first for ResultSetm then the Statement and at the end for the Connection object.
It's also important to know that any exceptions that occur when the close methods is automatically called are suppressed. These suppressed exceptions can be retrieved by getsuppressed() method defined in the Throwable class.
Source: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Ignoring exceptions which occur in a 'finally' block is generally a bad idea unless one knows what those exceptions will be and what conditions they will represent. In the normal try/finally usage pattern, the try block places things into a state the outside code won't be expecting, and the finally block restores those things' state to what the outside code expects. Outside code which catches an exception will generally expect that, despite the exception, everything has been restored to a normal state. For example, suppose some code starts a transaction and then tries to add two records; the "finally" block performs a "rollback if not committed" operation. A caller might be prepared for an exception to occur during the execution of the second "add" operation, and may expect that if it catches such an exception, the database will be in the state it was before either operation was attempted. If, however, a second exception occurs during the rollback, bad things could happen if the caller makes any assumptions about the database state. The rollback failure represents a major crisis--one which should not be caught by code expecting a mere "Failed to add record" exception.
My personal inclination would be to have a finally method catch exceptions that occur and wrap them in a "CleanupFailedException", recognizing that such failure represents a major problem and such an exception should not be caught lightly.
One solution, if the two Exceptions are two different classes
try {
...
}
catch(package1.Exception err)
{
...
}
catch(package2.Exception err)
{
...
}
finally
{
}
But sometimes you cannot avoid this second try-catch. e.g. for closing a stream
InputStream in=null;
try
{
in= new FileInputStream("File.txt");
(..)// do something that might throw an exception during the analysis of the file, e.g. a SQL error
}
catch(SQLException err)
{
//handle exception
}
finally
{
//at the end, we close the file
if(in!=null) try { in.close();} catch(IOException err) { /* ignore */ }
}
Why do you want to avoid the additional block? Since the finally block contains "normal" operations which may throw an exception AND you want the finally block to run completely you HAVE to catch exceptions.
If you don't expect the finally block to throw an exception and you don't know how to handle the exception anyway (you would just dump stack trace) let the exception bubble up the call stack (remove the try-catch from the finally block).
If you want to reduce typing you could implement a "global" outer try-catch block, which will catch all exceptions thrown in finally blocks:
try {
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
try {
...
} catch (Exception ex) {
...
} finally {
...
}
} catch (Exception ex) {
...
}
After lots of consideration, I find the following code best:
MyResource resource = null;
try {
resource = new MyResource();
resource.doSomethingFancy();
resource.close();
resource = null;
} finally {
closeQuietly(resource)
}
void closeQuietly(MyResource a) {
if (a!=null)
try {
a.close();
} catch (Exception e) {
//ignore
}
}
That code guarantees following:
The resource is freed when the code finished
Exceptions thrown when closing the resource are not consumed without processing them.
The code does not try to close the resource twice, no unnecessary exception will be created.
If you can you should test to avoid the error condition to begin with.
try{...}
catch(NullArgumentException nae){...}
finally
{
//or if resource had some useful function that tells you its open use that
if (resource != null)
{
resource.Close();
resource = null;//just to be explicit about it was closed
}
}
Also you should probably only be catching exceptions that you can recover from, if you can't recover then let it propagate to the top level of your program. If you can't test for an error condition that you will have to surround your code with a try catch block like you already have done (although I would recommend still catching specific, expected errors).
You could refactor this into another method ...
public void RealDoSuff()
{
try
{ DoStuff(); }
catch
{ // resource.close failed or something really weird is going on
// like an OutOfMemoryException
}
}
private void DoStuff()
{
try
{}
catch
{
}
finally
{
if (resource != null)
{
resource.close();
}
}
}
I usually do this:
MyResource r = null;
try {
// use resource
} finally {
if( r != null ) try {
r.close();
} catch( ThatSpecificExceptionOnClose teoc ){}
}
Rationale: If I'm done with the resource and the only problem I have is closing it, there is not much I can do about it. It doesn't make sense either to kill the whole thread if I'm done with the resource anyway.
This is one of the cases when at least for me, it is safe to ignore that checked exception.
To this day I haven't had any problem using this idiom.
try {
final Resource resource = acquire();
try {
use(resource);
} finally {
resource.release();
}
} catch (ResourceException exx) {
... sensible code ...
}
Job done. No null tests. Single catch, include acquire and release exceptions. Of course you can use the Execute Around idiom and only have to write it once for each resource type.
Changing Resource from best answer to Closeable
Streams implements Closeable Thus you can reuse the method for all streams
protected void closeQuietly(Closeable resource) {
if (resource == null)
return;
try {
resource.close();
} catch (IOException e) {
//log the exception
}
}
I encountered a situation similar where I couldn't use try with resources but I also wanted to handle the exception coming from the close, not just log and ignore it like closeQuietly mechanism do. in my case I'm not actually dealing with an output stream, so the failure on close is of more interest than a simple stream.
IOException ioException = null;
try {
outputStream.write("Something");
outputStream.flush();
} catch (IOException e) {
throw new ExportException("Unable to write to response stream", e);
}
finally {
try {
outputStream.close();
} catch (IOException e) {
ioException = e;
}
}
if (ioException != null) {
throw new ExportException("Unable to close outputstream", ioException);
}

Closing a Java FileInputStream

Alright, I have been doing the following (variable names have been changed):
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... handle error ...
}
finally
{
if (fis != null)
fis.close();
}
Recently, I started using FindBugs, which suggests that I am not properly closing streams. I decide to see if there's anything that can be done with a finally{} block, and then I see, oh yeah, close() can throw IOException. What are people supposed to do here? The Java libraries throw too many checked exceptions.
For Java 7 and above try-with-resources should be used:
try (InputStream in = new FileInputStream(file)) {
// TODO: work
} catch (IOException e) {
// TODO: handle error
}
If you're stuck on Java 6 or below...
This pattern avoids mucking around with null:
try {
InputStream in = new FileInputStream(file);
try {
// TODO: work
} finally {
in.close();
}
} catch (IOException e) {
// TODO: error handling
}
For a more detail on how to effectively deal with close, read this blog post: Java: how not to make a mess of stream handling. It has more sample code, more depth and covers the pitfalls of wrapping close in a catch block.
Something like the following should do it, up to you whether you throw or swallow the IOException on attempting to close the stream.
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
... process ...
}
catch (IOException e)
{
... blah blah blah ...
}
finally
{
try
{
if (fis != null)
fis.close();
}
catch (IOException e)
{
}
}
You could use the try-with-resources feature added JDK7. It was created precisely to deal with this kind of things
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
The documenation says:
The try-with-resources statement ensures that each resource is closed
at the end of the statement.
You could also use a simple static Helper Method:
public static void closeQuietly(InputStream s) {
if (null == s) {
return;
}
try {
s.close();
} catch (IOException ioe) {
//ignore exception
}
}
and use this from your finally block.
Nothing much to add, except for a very minor stylistic suggestion. The canonical example of self documenting code applies in this case - give a descriptive variable name to the ignored IOException that you must catch on close().
So squiddle's answer becomes:
public static void closeQuietly(InputStream s) {
try {
s.close();
} catch (IOException ignored) {
}
}
In most cases, I find it is just better not to catch the IO exceptions, and simply use try-finally:
final InputStream is = ... // (assuming some construction that can't return null)
try {
// process is
...
} finally {
is.close();
}
Except for FileNotFoundException, you generally can't "work around" an IOException. The only thing left to do is report an error, and you will typically handle that further up the call stack, so I find it better to propagate the exception.
Since IOException is a checked exception, you will have to declare that this code (and any of its clients) throws IOException. That might be too noisy, or you might not want to reveal the implementation detail of using IO. In that case, you can wrap the entire block with an exception handler that wraps the IOException in a RuntimeException or an abstract exception type.
Detail: I am aware that the above code swallows any exception from the try block when the close operation in the finally block produces an IOException. I don't think that is a big problem: generally, the exception from the try block will be the same IOException that causes the close to fail (i.e. it is quite rare for IO to work fine and then fail at the point of closing). If this is a concern, it might be worth the trouble to "silence" the close.
The following solution correctly throws an exception if close fails without hiding a possible exception before the close.
try {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
} catch(IOException exc) {
// kernel panic
}
This works because calling close a second time has no effect.
This relies on guava Closeables, but one can write its own closeQuietly method if preferred, as shown by squiddle (see also serg10).
Reporting a close error, in the general case, is important because close might write some final bytes to the stream, e.g. because of buffering. Hence, your user wants to know if it failed, or you probably want to act somehow. Granted, this might not be true in the specific case of a FileInputStream, I don't know (but for reasons already mentioned I think it is better to report a close error if it occurs anyway).
The above code is a bit difficult to grasp because of the structure of the embedded try blocks. It might be considered clearer with two methods, one that throws an IOException and one that catches it. At least that is what I would opt for.
private void work() throws IOException {
InputStream in = new FileInputStream(file);
try {
// work
in.close();
} finally {
Closeables.closeQuietly(in);
}
}
public void workAndDealWithException() {
try {
work();
} catch(IOException exc) {
// kernel panic
}
}
Based on http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (referenced by McDowell).
Hopefully we will get closures in Java some day, and then we will lose lots of the verbosity.
So instead there will be a helper method somwhere in javaIO that you can import, it will probably takes a "Closable" interface and also a block. Inside that helper method the try {closable.close() } catch (IOException ex){ //blah} is defined once and for all, and then you will be able to write
Inputstream s = ....;
withClosable(s) {
//your code here
}
Are you concerned primarily with getting a clean report from FindBugs or with having code that works? These are not necessarily the same thing. Your original code is fine (although I would get rid of the redundant if (fis != null) check since an OutOfMemoryException would have been thrown otherwise). FileInputStream has a finalizer method which will close the stream for you in the unlikely event that you actually receive an IOException in your processing. It's simply not worth the bother of making your code more sophisticated to avoid the extremely unlikely scenario of
you get an IOException and
this happens so often that you start to run into finalizer backlog issues.
Edit: if you are getting so many IOExceptions that you are running into problems with the finalizer queue then you have far far bigger fish to fry! This is about getting a sense of perspective.

Categories