Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Is there a "best practice" for how much code to put inside a try/catch block?
I have posted 3 different scenarios below.
I did not include behavior in each catch block and i did not include the finally block. This was to improve readability for viewers. Assume each catch does something differently. And assume the finally will be closing the stream. Just trying to create an easy to read example for future readers.
Control, no try/catch.
Code with 1 try/catch for each place needed.
Code with only 1 try/catch surrounding whole code block.
What is generally accepted as the best practice and why?
Scenario 1
Code without try/catch, just for control.
BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
String line;
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
this.doSomething(object);
}
bufferedReader.close();
Scenario 2
Code with a try/catch block for each individual place needed.
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader("somepath"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String line;
try {
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
this.doSomething(object);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
Scenario 3
Code with 1 try/catch surrounding the whole block of code.
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
String line;
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
this.doSomething(object);
}
bufferedReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You should scope your try/catches based on the following criteria:
do you need to do different things based on where the exception came from?
do you need to do different things based on which exception was thrown?
what code needs to be skipped (aka is "invalid") when a given exception is thrown?
answering these questions will enable you to determine the appropriate scope for any try/catch block.
I'd put as little in the try-catch as possible.
This allows you to very easily move pieces of code into separate methods which is a good coding practice (obeying single responsibility principle; see the book "Clean Code: A Handbook of Agile Software Craftsmanship" by Robert C. Martin).
Another advantage is that you can quickly identify which code actually can throw an exception.
Scenario 2 seems a bit extreme though, and since the method is pretty small, Scenario 3 seems like the best choice.
However, you need to have your "close" statement in a finally block.
This is a matter of opinion. I've seen each of these patterns a lot.
Pattern 1 is only good when your method can throw the excpetions and have something up the caller chain handle that. That is often desireable. However, since the close call is not in a finally block, it might not be called. At least, use a try-finally block.
Pattern 2 isn't good, since if the first try-catch block handles an exception, the rest of the method is useless.
Pattern 3 is okay, but not great, as printing stack traces hides the fact that the operation failed. What will the caller do if it thinks the operation occurred when it didn't. Also, the closes might not have happened, which can lead to program failure.
In pseudo code, this variant of pattern 3 is better:
Declare Streams, connections, etc.
try
Initialize streams, connections, etc,
Do work.
catch (optional)
Catch and handle exceptions.
Do not simply log and ignore.
finally
Close connections and streams in reverse order.
Remember, closing these objects can throw,
so catch exceptions the close operation throws.
End.
If you are using Java 7, use try-with-resources:
try (BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
this.doSomething(object);
}
}
Have IOExceptions bubble up to the caller.
You should go with the third scenario.
If the bufferedReader hits an exception then on creation in the second scenario then it you try to readLine() on it, it will hit another exception. No point in raising multiple exceptions for the same problem.
You should also close your bufferedReader in the finally block.
BufferedReader bufferedReader;
try {
bufferedReader = new BufferedReader(new FileReader("somepath"));
String line;
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
this.doSomething(object);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bufferedReader != null)
bufferedReader.close();
}
I consider an Exception being an uncoditionally returned result type. So when I work with try-catch sections, I'm trying to answer questions
Should I handle an unexpected result here or should I propagate it on a higher level?
Which unexpected results should I handle?
How to handle them?
In 95% of the cases I don't go further than the first point, so I just propagate the errors.
For file processing I use try-with-resources an re-throw the IOException with throw new RuntimeException(e).
I think it's similar with how much code to put in method. Try to write try/catch/finally which takes no more than one screen. I want to say it's not a problem to wrap entire method body into try{} block, but you should separate this code into several methods if it became too long.
You example with one try/catch each doesn't make sense because you just print a stack trace and continue - knowing already that it will be a failure. You might as well try/catch the whole lot, or add throws SomeException to the method signature and let the calling method decide what went wrong.
Also, don't worry about squeezing too much inside a try/catch. You can always extract that code into another method. Readability is one of the single most important aspects of programming.
The third option is certainly best. You don't want your try/catch block to become unwieldy, but in this example, it is short enough that you do not need to divide it as you have done in your second option.
Not scenario 2. If the FileReader or BufferedReader constructor throws, then bufferedReader will be null but the next try/catch will still execute. Therefore you'll get an (uncaught) exception at bufferedReader.readLine -- a NullPointerException. Between scenarios 1 and 3, I generally like 3 more because it doesn't require the caller to catch. BTW, you don't need to catch FileNotFoundException explicitly, because it inherits from IOException and therefore that catch block will catch both.
jtahlborn already has the correct answer.
Unfortunately sometimes, proper exception handling can be pretty bloated.
One should be ready to deal with it, if required.
Another possible scenario are nested try-catch blocks.
Consider:
BufferedReader bufferedReader = new BufferedReader(new FileReader("somepath"));
try {
String line;
while ((line = bufferedReader.readLine()) != null) {
Object object = new Object();
try {
this.doSomething(object);
} catch (InvalidArgumentException iae) {
throw new RuntimeErrorException("Failed to process line " + line + ", iae);
} catch (ParserWarning e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
bufferedReader.close();
}
Related
Apparently I am always calling FileReader#close() and FileWriter#close(), but some of my files remained locked by my own code.
How to
1) close file fully?
2) check, where in the code it was opened and not closed?
The question is vague and is missing context, so it makes it difficult to answer and encourages assumptions, never a good place to start from...
However, if you are doing something similar to...
try {
FileReader fr = new FileReader(new File("..."));
// Read file...
fr.close();
} catch (IOException exp) {
exp.printStackTrace();
}
Then if an exception occurs for some reason (or the code returns before it reaches the close statement), then close will never be called...
Prior to Java 7, one would typically do something like...
FileReader fr = nulll;
try {
fr = new FileReader(new File("..."));
// Read file...
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
// Avoid NullPointerException's
if (fr != null) {
fr.close();
}
} catch (Exception exp) {
}
}
This ensures that regardless of what happens between the try-catch, finally will always be called and you can take steps to ensure that the resource is closed.
With Java 7, you can now take advantage of the "try-with-resources" feature...
try (FileReader fr = new FileReader(new File("..."))) {
fr = ;
// Read file...
} catch (IOException exp) {
exp.printStackTrace();
}
Which is basically a short-cutted version of the try-catch-finally example block.
If you are using the FileLock functionality, then you also need to ensure that you releasing the FileLock when you are done with, in a similar fashion to the try-catch-finally example above, but file locking will only ensure that different processes can't read/write the simultaneously, it doesn't protect you against multiple threaded access...
I have discovered possibility of having code "after return" using finally, here is some example:
int foo() {
BufferedReader br = ...;
try {
// cca 20 lines with 4 returns in different if-else clauses etc
//example:
if(something) {
return 0;
} else {
return 1;
}
} finally {
br.close();
}
}
As (in my opinion much more lazy) alternativity to:
int foo() {
BufferedReader br = ...;
int toReturn;
// cca 20 lines with 4 ASSIGMENTS in different if-else clauses etc
//example:
if(something) {
toReturn = 0;
} else {
toReturn = 1;
}
br.close();
return toReturn;
}
So, the question is, which is faster, more readable, and yes, in this case, i am really closing a BufferedReader, so is try-finnaly for this or am i using it wrong way?
Without using the try/catch/finally, if an exception is thrown, your BufferedReader won't be closed properly, causing a memory leak, potential unwanted file locking...
Using finally, your BufferedReader will be closed, even if an exception is thrown while processing the try block.
But as your BufferedReader instantiation can also throw an exception, you should include it in your try block:
BufferedReader br = null;
try {
br = ...;
// do your stuff
}
catch (Exception e) {
// handle exception
}
finally {
if(br != null)
br.close();
}
If you're using Java 7 or newer, go with the elegant Try-with-resources, as stated by Arnaud.
If there is an exception throws, both your code fail since first case you are not catching exception and second case there are no evidence of handling exception.
finally will execute any way here.
If your BufferedReader get input by file read, in a case which file not found both ways are not useful.
The second one is actually unacceptable. You will not close the buffer in case of exception.
I advise you to use the try-with-resources statement (intended for that purpose):
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
//do what you want with the buffer. It will automatically be closed.
return;
}
See The try-with-resources Statement
am i using it wrong way?
yes you are. What if say something is a method call and it throws exception, then your br is never closed. While finally makes sure that in any case it will get execute*
`* - there are some conditions where you can avoid finally clause execution
try {
bufferedReader = new BufferedReader(new FileReader(new File(file,FILENAME)));
String readLine = bufferedReader.readLine();
//do stuff
} catch(Exception e) {
throw e;
} finally {
if (bufferedReader!=null)
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
will the bufferedReader closing be invoked in any case in this code?
yes it invokes in any case( if it is not null in you case).According to java docs
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.
If you are using Java7 then I strongly recommond to use try-with-resources Statement.Then you do not require to write the finally block in your code.
try-with-resouce example
try (BufferedReader bufferedReader =
new BufferedReader(new FileReader(new File(file,FILENAME)));) {
String readLine = bufferedReader.readLine();
//do stuff
} catch(Exception e) {
throw e;
}
Note:
finally block won't execute in only one case. That is when JVM shutdown(generally with System.exit() statement or when the JVM process is killed externally). In all other cases the finally is guaranteed to execute
Finally is always executed, even if the exception is thrown or not. So it will execute the bufferedReader.close(); when bufferedReader is not null
I would refer you to this question:
In Java, is the "finally" block guaranteed to be called (in the main method)?
Basically, the finally block will always get run, with one exception: If the JVM exits before the finally block executes.
As to whether the bufferedReader executing - as written, so long as it's not null, yes, with the above noted exception
Yes, this code will close bufferedReader in any situation. But in general the code looks like a mess. Java 7 try-with-resources is the best solution of closing resources
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(file,FILENAME))) {
//do stuff
}
finally in a try/catch block means that it will happen no matter what.
Also, the exception would be better stated as IOException.
There is really no reason to have a catch block throw an exception in this situation.
Note: It is true that invoking System.exit() will terminate your could as soon as it is encountered and will result in the application being terminated by the JVM (Java Virtual Machine).
I just write a simple commandwrapper in java, this is construction function:
Process process;
Thread in;
Thread out;
public CommandWrapper(Process process) {
this.process = process;
final InputStream inputStream = process.getInputStream();
// final BufferedReader
//final BufferedReader r = new BufferedReader(new InputStreamReader(inputStream));
final byte[] buffer = new byte[1024];
out = new Thread() {
// String line;
int lineNumber = 0;
public void run() {
try {
while (true) {
int count = inputStream.read(buffer);
System.out.println(lineNumber + ":"
+ new String(buffer, 0, count - 1));
// line=r.readLine();
// System.out.println(lineNumber+":"+line);
lineNumber++;
}
} catch (Exception e) {
}
}
};
final BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
final OutputStream outputStream = process.getOutputStream();
in = new Thread() {
String line;
public void run() {
try {
//while (true) {
outputStream.write((reader.readLine() + "/n")
.getBytes());
outputStream.flush();
//}
} catch (Exception e) {
}
}
};
}
public void startIn() {
in.start();
}
This is when it invoke:
public static void main(String[] args) {
try {
CommandWrapper command = new CommandWrapper(Runtime.getRuntime()
.exec("wget www.google.com"));
//command.startIn();
command.startOut();
} catch (Exception e) {
e.printStackTrace();
}
}
It works OK when I run simple command like ls -l or other local commander, but when I want to run wget command it is print out nothing as output. I do know why.
From the code you've shown and your description of how you use it, the best guess is that an exception occurs, and you silently swallow it. This happens whenever you have an empty catch-block, like this:
catch (Exception e) {
}
You happen to have one in the run() method of your out thread.
Silently swallowing exceptions is extremely bad practice.
You should never ever ever do this! Depending on your application the appropriate solution varies, but since you're writing a console application you probably want to print the stack trace of the exception. In Java, this is done with e.printStackTrace():
catch (Exception e) {
e.printStackTrace();
}
Another option (which might not be appropriate in this specific case) is to rethrow the exception, possibly after wrapping it in another exception (for example one you've written specifically for your application):
catch (Exception e) {
throw e;
}
// or
catch (Exception e) {
throw new MyOwnException(e);
}
Doing either of these two (printing stack trace or rethrowing) will ensure that no exceptions go unnoticed.
However, no rule without exceptions ;)
There are cases when it is appropriate to have empty catch-clauses. If you know that some operation might throw an exception and you just want to proceed when it happens, an empty catch-clause is a good way to do it. However, the cases where this is appropriated are limited to (at least) the following conditions:
You must know the specific type of the exception. You never want to catch a general exception (i.e. catch (Exception e) since that might be thrown for any reason which you cannot possibly predict. If you use empty catch clauses, always catch specific exception type (such as IOException).
You must know why the exception was thrown. You should only swallow exceptions that you know the origin of. If you swallow any other exceptions, you'll end up like in this situation, where your code doesn't do what you expect and you can't understand why. Swallowed exceptions are extremely difficult to debug, since they are, well, swallowed, and thereby hidden.
You must know that you don't care about the exception. The reason to use empty catch-clauses is mainly (read: only) to handle situations where the code you're using treats something as exceptional, while you do not. By exeptional in this context we mean "something that shouldn't really happen, and if it does, something is seriously wrong."
An example of when empty catch-clauses are appropriate:
Say that you are using someone elses code that opens a file for reading, given the absolute path of the file. Most such routines throw exceptions if the file does not exist - it is the job of the client code (i.e. the code that calls the "open file routine") to ensure that the file exists before trying to open it. Exceptions will also be thrown if, for example, the user running the program does not have permissions to read the file.
Now, you might not really care why the file couldn't be opened, but if it couldn't you just want to keep going - in that case, you swallow all exceptions related to reading the file (in Java, likely an IOException of some sort). Note that you do not swallow all exceptions - only the ones related to opening the file!
I am trying to return a String from the following method.
public String openCon() {
try {
Scanner scan = new Scanner(System.in);
URL sitex = new URL("http://" + scan.nextLine());
URLConnection connection = sitex.openConnection();
Object content = sitex.getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(sitex.openStream()));
String str;
String x = "1";
while ((str = in.readLine()) != null) {
x += str;
}
in.close();
return x;
}
catch(Exception e) {
System.out.println(e);
}
}
The problem isn't returning from the try block - the problem is that you aren't returning anything if an exception is thrown. You're catching the exception... but then reaching the end of the method without returning anything. (To put it in more technical terminology: the end of a non-void method should not be reachable.)
Personally, I would just remove the catch block entirely, and add throws declarations for any exceptions which are thrown within the body. You're not really handling the exceptions - you're just printing them out and ignoring them, which is very rarely a good idea. Catching Exception is usually a pretty bad idea to start with.
As an aside, you should also close your BufferedReader and URLConnection values in a finally block so they're closed even in the case of an exception. I'd also suggest either passing a fixed encoding name to InputStreamReader, or using a higher-level HTTP client API which will use the content-type header from the response. Oh, and use StringBuilder instead of string concatenation in a loop.
Why not initialise the variable before the try statement, and place the return statement after it?
If there's an exception before the return statement, the method won't return anything. Since you're not really handling the exception, I recommend you just let it bubble up and handle it at a higher level. This may be the main method if there's no better place. You will need to declare the method as throws IOException and possibly add other exception classes.
Also, use try-with-resources to ensure your instances (BufferedReader and InputStreamReader) are closed properly.
You should return something in the catch block, for example:
catch(Exception e) {
System.out.println(e);
return "";
}
Use:
String result = ""
try{
result = "OK";
}catch (Exception e){
result = e.toString();
}finally{
return result;
}