I wonder if the following two swnippest are semantically identical, and, if not, what are the differences (we assume that we want to compute a result of type R, and want to guard against exception X that may be thrown in the course of doing so):
public R tcf(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
finally {
... clean up ....
}
}
and the following:
public R tc(....) {
try {
R some = ...;
... compute the result ....
return some;
}
catch (X exception) {
... exception handling ....
}
}
public R tf(....) {
try {
return tc(....); // wrap the try-catch in tc()
}
finally {
... clean up ....
}
}
As far as I can see, it boils down to if a try-catch block wrapped in a try block with finally is the same, semantically, as a try-catch-finally block, assuming that the code in the finally and catch phrases stays the same and the outer try block just promotes the result of the inner one.
Practical relevance: Given a code base that does not make use of try-catch-finally, when it should, and given that for some reason, one cannot toch that code, one could more or less mechanically generate a layer of wrapper methods that add the finally.
I am fully aware of the fact, that for many reasons, one should use the try ... catch ... finally whenever possible. Specifically, I am not suggesting in any way that one should refactor the first example so that it looks like the second.
Rather, I want to make sure that example 2 can safely be refactored to example 1.
Functionally, they are equivalent.
I think it's good style to perform cleanup in the same method that has allocated the resources in question. In some cases this is the only practical way to go about things (for example, if the cleanup involves variables that are local to tcf/tc).
Also, if tc doesn't clean up after itself, the cleanup becomes part of the function's contract, as a caller's obligation. This makes the design more error-prone, since the cleanup is easy to forget or get wrong. Additionally, if the steps involved in the cleanup in any way change, every single caller would need to be tracked down and updated.
Bottom line: if the cleanup can be performed in tcf, it should be.
They are the same, however. The try/finally should always be right after the recourse (that finally releases) is claimed. (note that this happens just before the try)
For example:
getLock();
try {
doSomething()
}
finally {
releaseLock();
}
Because it is really easy to forget to clean up, it should always happen at the same location as the taking of the resource. Reason for this is that you should never burden your callers with something they always have to do (and you can do yourself)
Not performing the finally in the same method as the try/catch leaves you open to the method doing the try/catch at some point being called without the finally being executed, which is likely a bug.
I'd therefore not advise you to write it like that, though in the scenario you describe, having to add functionality through a finally when the method containing the try/catch can't be modified, it's the only way.
I think your description is pretty accurate in that the tf finally will execute in both cases and that the exception handling will be dealt with in either tcf or tf catch block.
That is, in example (1): if an exception occurs in your try, flow will execute your catch block followed by your finally block. In example (2), in tc, if an exception occurs in your try block, flow will continue in your catch block and then (presuming the exception isn't re-thrown) return to the calling line in tf. On completion of your tf try block, flow will continue in your tf finally block.
I guess the main implication to be aware of, and that you may not be able to correct in the way you suggest, is that:
If you implement your code as in your second example, you won't be able to necessarily access the tc resources from tf to be able to clean them up.
Even if you can, you're cleaning up resources at a layer that is not close to the resource usage and may not even be used by other client code of the framework. I guess that's a question of documentation and training.
Both are identical. but finally is used when you are having a risk of breaking the function in between or want to release some resources held by the function. in that case catch is skipped but finally will definitely execute.
try can be used either with catch or finally or both. finally generally can't show the exception occurred but catch can trace the exception.
Related
I am working on a Java plugin for a framework.
I have written my code in such a way that entryPoint function looks like below (consider this is the starting point, main function)
function entryPoint()
{
try{
//some code block
subFunction1();
subFunction2();
}
catch(Exception e) {}
catch(IOException ioe) {}
catch(NullPointerException npe){}
}
function subFunction1() throws IOException
{
//some code
}
function subFunction2() throws NullPointerException
{
//some code
}
So the idea is, all the sub functions throws specific exceptions to major function and
we catch these exceptions in the major functions and do handling.
Is this way correct? If not please suggest better way.
The order of the catch statements should be changed. Since the first catch will match all Exceptions, the following two will never be triggered.
An NPE is in most cases unexpected and not recoverable. Catching it implies that the application is able to recover from it and run regardless. Is it really the case?
Even if the NPE is recoverable, it is a better practice to check for != null instead of relying on exceptions for command flow. This is for conceptual reasons (exception-based command flow requires more code, is less readable, the intention is often unclear) as well as for performance reasons.
All Exceptions are swallowed - no logging or rethrowing happens. This way, no one will know if and when something goes wrong because there are no exceptions logged. In most cases, users, other developers and maintainers expect almost all exceptions to be truly exceptional and therefore logged.
Do not catch or throw NullPointerException and Exception's catch block should be the last one
I think this approach is perfect. One should try to handle specific exception rather handling all in one. Putting a try-catch block just for the heck of it is not use of it, but abuse of try-catch thing.
Yeah Exception should be the last one to be handled.Missed this.
In short your intent is good and syntactically you can depend on compiler.
You should do the exception-handling the same way you would do it, if it was no plugin. It depends on you application, if you can handle all exceptions in one major method. If there are case, in which you can continue work, than this could be difficult this way.
The only thing that I would do regarding the plugin-thing is an all surrounding 'catch-all' and maybe some special cases to do some more detail logging. And this also has just to be done, if the framework doesn't do it itself.
I think it is best to catch an exception at the first possible place where you can actually resolve the resulting problem.
An example:
function int divide(int a, int b) throws DivisionByZeroException {
if(b == 0){
throw new DivisionByZeroException();
}
return a / b;
}
function int doCalculationsAndStuff(int a, int b) throws DivisionByZeroException {
int result = divide(a, b);
...
return result;
}
function void main() {
try {
int a = userInput();
int b = userInput();
int result = doCalculationsAndStuff(a, b);
print("result: " + result);
} catch(DivisionByZeroException e) {
print("Division by zero happened. But i catched it for you =).");
}
}
It wouldn't make sense to handle the exception in divide() or doCalculationsAndStuff(). Because what value would you return in case of a division by zero? Nothing, right that's why we throw the exception and handle it in the main function where we give the user of our calculator app some feedback.
Now back to your question. If the entryPoint function is the first place where you can resolve the problems that occur in your subfunctions than thats a good place to handle them.
This question already has answers here:
Is a finally block without a catch block a java anti-pattern?
(12 answers)
Closed 9 years ago.
What is the best practice in using Try Catch Finally block? Do you prefer to use only try finally block and not try catch block? I always thought that try catch finally is the best practice to use. However, in part of the code I am working with I have seen code like this:
try{
doSomething();
}
finally{
doSomethingElse();
}
Since they don't catch the exception it was really hard for me to debug the code. It wasn't a really good practice to me not using catch and only finally, but I might be wrong.
To best of my understanding, this is not really a good practice. Basically, we are not making use of what try catch was intended to be used for. I have found similar questions as well.
My questions is: "Do you agree with me on the following hypothesis: The best practice is to use try catch finally together and not try finally." If you do not agree, would you please provide me with an example of when to use try finally instead of try catch finally and why you think try finally is better than try catch?
I disagree, if you cannot do anything about an exception being thrown, but something further up your caller hierarchy can, then use the finally to clean up your resources and let the caller deal with cleaning up after the exception is thrown.
The purpose of the finally construct is to provide code that will always execute, even if an exception is thrown.
The try / finally (no catch) allows you to write code that is guaranteed to execute even if a runtime exception is thrown by the code inside the try block.
This is good in situations where you are using code that might throw runtime exceptions but does not throw checked exceptions. An example of this is Spring DAO support; which wraps IOExceptions in runtime exceptions.
Generally try-finally is used to assure that some piece of code gets executed irrespective if the exception occurs or not.
Catch block is generally missing because code in try block does not throw any checked exception which can be caught.
Eg:
try {
if(str.length() > 0) { // If str is null, it can throw NullPointer and hence code below it wont execute
// some code
}
}finally {
// Will be performed even if any unchecked exception is thrown
// Must contain code which has to be performed at any cost like releasing occupied memory
}
There are three possibilities, try+catch, try+finally, or try+catch+finally. They all have their uses.
Use the catch with try when there's something you can usefully do to handle the exception, such as report the fact that the exception has occurred.
The code inside the finally block always runs, independent of whether an exception occurs or not, so use finally with try when there's cleaning up to do that's always got to happen. An example would be closing a file if it's been successfully opened.
I do not agree.
try{}finally{} should be used in cases where you cannot handle the exception, but are required to clean up resources.
A try{}finally{} block will not cause the exception to "disappear" as you seem to think it will. It will be thrown up the stack and be handled somewhere else. If you are unable to see the exception in your current application it's because it's being thrown away elsewhere.
try {
connection = createConnection();
}
finally {
closeConnection(connection) //Free database connection.
}
In this case, you may not have any ability to handle an SQL exception, but you still want to free the database connection.
I've discovered an odd dichotomy in the way Eclipse reports the "The local variable may not have been initialized" error. This error normally occurs if I declare a variable outside a try/catch block, initialize it inside the try/catch block, and then use it after the try/catch block:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
r.nextInt(); //Error: The local variable r may not have been initialized
This makes sense. I can avoid the error either by initializing the variable to null when I declare it, or by ensuring that the program's control flow never reaches the next statement if an exception occurs inside the try/catch block. Thus, in the case where I really can't continue executing if the variable initialization failed, I can do this:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
throw new RuntimeException("Initialize secure random number generator failed");
}
r.nextInt(); //No error here
However, I recently tried using System.exit to stop the program instead of a RuntimeException to make my program's console output cleaner. I would think these are equivalent because both prevent the program from continuing execution, but I discovered that Eclipse does not agree:
Random r;
try {
r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
System.err.println("Couldn't initialize secure random number generator");
System.exit(1);
}
r.nextInt(); //Error: The local variable r may not have been initialized
Why does Eclipse still give me the "not initialized" error when execution could never reach r.nextInt() if an exception occurred? Is this a bug in Eclipse, or is there some way that execution could continue to r.nextInt() even after calling System.exit?
Good question, it also bugged me several times.
The problem is that unlike throwing an exception, just calling a method (and that's what System.exit(1); is) does generally not guarantee that the program flow stops. Sure, the documentation of System.exit() says that this method never returns normally. But while the semantics of throw are defined by the language itself, the semantics of System.exit() are just in the Javadocs.
My guess is that they just didn't bother to implement this special case yet. While there is a bug report where this topic is touched (https://bugs.eclipse.org/bugs/show_bug.cgi?id=126551, see comment 2), it is marked as "wont fix" because it seems to be too complicated.
Edit: As rlegendi pointed out, it is actually a problem of the Java compiler, not just of Eclipse. My solution so far was to just go with the plain old throw, (instead of some special throw() method) which (in anything else than a very small application) is better than System.exit() anyway.
This isn't a bug: in your second example it is guaranteed that r is initialized at the call site (you throw an exeption otherwise so that execution branch is closed).
In the first and third example you simply execute program code and leave r undefined. If you assign null to it either at the exception handling block or at the declaration it won't complain.
Btw it is not an Eclipse issue, it is defined by the JLS that you cannot use an uninitialized variable. Try compiling it with Java and you should get the exactly same output.
We have received Java code from a software supplier. It contains a lot of try-catch blocks with nothing in the catch part. They're all over the place. Example:
try {
spaceBlock.enable(LindsayModel);
} catch (Exception e) {
}
My questions are: Is the above acceptable practice? If so, when? Or should I just go ahead and remove all of these "bogus" try and catch statements?
To me this looks like terrible practice, but I'm not experienced enough in Java to tell for sure. Why catch errors if you're not going to do anything with them? Seems to me, you would only do that if you were confident that an exception would be of absolutely no consequence and you don't care if one occurs. However, this is not really the case in our particular application.
EDIT To give some context: We bought a Java-scriptable product from the supplier. Alongside the product, they provided a large proof-of-concept script tailored to our needs. This script came "free of charge" (though we wouldn't have bought the product if it hadn't come with the script) and it "works". But the script is a real pain to build upon, due to many things that even I as a Java novice recognise as awful practice, one instance being this bogus try-catch business.
This is indeed terrible practice. Especially the catching of Exception rather than something specific gives off a horrible smell - even a NullPointerException will be swallowed. Even if it is assured that a particular thrown exception is of no real consequence, one should always log it at the very least:
try {
// code
}
catch (MyInconsequentialException mie) {
// tune level for this logger in logging config file if this is too spammy
MY_LOGGER.warning("Caught an inconsequential exception.", mie);
}
However it is unlikely an exception is completely meaningless in this situation. I recommend researching exactly what exception(s) the application's code is intending to swallow here, and what they would really mean for the execution.
One important distinction is whether the try/catches are used to swallow checked exceptions. If this is the case, it probably indicates extreme apathy on the programmer's part - somebody just wanted his/her code to compile. At the least, the code should be amended:
try {
// code
}
catch (SpecificCheckedException sce) {
// make sure there is exception logging done farther up
throw new RuntimeException(sce);
}
This will rethrow the exception wrapped in an unchecked RuntimeException, effectively allowing the code to compile. Even this can be considered a bandaid however - best practice for checked exceptions is to handle them on an individual basis, either in the current method or farther up by adding throws SpecificCheckedException to the method signature.
As #Tom Hawtin mentioned, new Error(sce) can be used instead of new RuntimeException(sce) in order to circumvent any additional Exception catches farther up, which makes sense for something that isn't expected to be thrown.
If the try/catch is not being used to swallow checked exceptions, it is equally dangerous and should simply be removed.
Terrible, indeed. Swallowing an exception like this can be dangerous. How will you know if something bad has happened?
I'd feel better if the vendor wrote comments to document and acknowledge it ("We know what we're doing"). I'd feel even better if there was a strategy apparent in the code to deal with the consequences. Wrap it in a RuntimeException and rethrow; set the return value to an appropriate value. Anything!
"All over the place"? Are there multiple try/catch blocks littering the code? Personally, I don't like that idiom. I prefer one per method.
Maybe you should find a new vendor or write your own.
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
}
This looks like unfinished code. If the enable method throws an Exception then it will be caught and swallowed by the code. If it doesn't then it does not make sense to try to catch a non occuring exception.
Check to see the methods and where their signatures are not followed by throws exceptionName, then remove the empty try-catch statements from the places they are called.
You can theoretically put try-catch around any statement. The compiler will not complain about it. It does not make sense though, since this way one may hide real exceptions.
You can see this as a sign of bad code quality. You should probably be prepared to run into problems of different type too.
It's not the best:
It hides evidence of the exception so debugging is harder
It may cause features to fail silently
It suggests that the author might actually have wanted to handle the exception but never got around to it
So, there may be cases where this is OK, such as an exception that really is of no consequence (the case that comes to mind is Python's mkdirs, which throws an exception if the directory already exists), but usually, it's not so great.
Unfortunately you cannot just remove it, because it the try block throws a checked exception then it will have to be declared in the throws clause of the method. The callers of the method will then have to catch it (but not if the callers also have this catch (Exception e) {} abomination).
As an alternative, consider replacing it with
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
}
Since RuntimeException (and classes that extend it) are unchecked exceptions they do not need to be declared in the throws clause.
What did your contract with the supplier specify? If what they wrote, bad practice and all, meets the spec then they will charge you for a rewrite.
Better to specify a set of tests that will enter many or all of those try-catch blocks and hence fail. If the tests fail you have a better argument to make them fix their terrible code.
Horrible idea on the face of it, totally depends on what you're actually calling. Usually it's done out of laziness or habituated bad practices.
Actually ... not so fast.
There are legitimate cases for ignoring an exception.
Suppose that an exception has happened already, and we're already in a catch(). While in the catch(), we want to make best effort to clean up (which could fail, too). Which exception to return?? The original one, of course. The code looks like this:
try {
something-that-throws();
} catch(Exception e) {
try {
something-else-that-throws();
} catch(Exception e1) {}
throw e;
}
When we really don't care whether an operation succeeds, but (unfortunately) the operation's author throws an exception if a failure occurs.
if (reinitialize) {
try {
FileUtils.forceDelete(sandboxFile); // delete directory if it's there
} catch(Exception e) {}
}
The above saves a rather tortured attempt to see if sandboxFile actually exists before deleting it anyway.
I've been told that there is some overhead in using the Java try-catch mechanism. So, while it is necessary to put methods that throw checked exception within a try block to handle the possible exception, it is good practice performance-wise to limit the size of the try block to contain only those operations that could throw exceptions.
I'm not so sure that this is a sensible conclusion.
Consider the two implementations below of a function that processes a specified text file.
Even if it is true that the first one incurs some unnecessary overhead, I find it much easier to follow. It is less clear where exactly the exceptions come from just from looking at statements, but the comments clearly show which statements are responsible.
The second one is much longer and complicated than the first. In particular, the nice line-reading idiom of the first has to be mangled to fit the readLine call into a try block.
What is the best practice for handling exceptions in a funcion where multiple exceptions could be thrown in its definition?
This one contains all the processing code within the try block:
void processFile(File f)
{
try
{
// construction of FileReader can throw FileNotFoundException
BufferedReader in = new BufferedReader(new FileReader(f));
// call of readLine can throw IOException
String line;
while ((line = in.readLine()) != null)
{
process(line);
}
}
catch (FileNotFoundException ex)
{
handle(ex);
}
catch (IOException ex)
{
handle(ex);
}
}
This one contains only the methods that throw exceptions within try blocks:
void processFile(File f)
{
FileReader reader;
try
{
reader = new FileReader(f);
}
catch (FileNotFoundException ex)
{
handle(ex);
return;
}
BufferedReader in = new BufferedReader(reader);
String line;
while (true)
{
try
{
line = in.readLine();
}
catch (IOException ex)
{
handle(ex);
break;
}
if (line == null)
{
break;
}
process(line);
}
}
The basic premise here is false: the size of a try block makes no difference in performance. Performance is affected by actually raising exceptions at runtime, and that's independent of the size of the try block.
However, keeping try blocks small can lead to better programs.
You might catch exceptions to recover and proceed, or you might catch them simply to report them to the caller (or to a human, via some UI).
In the first case, failures from which you can recover are often very specific, and this leads to smaller try blocks.
In the second case, where an exception is caught so that it can be wrapped by another exception and re-thrown, or displayed to the user, small try blocks mean that you know more precisely which operation failed, and the higher-level context in which that call was made. This allows you to create more specific error reports.
Of course, there areā¦ exceptions (sorry!) to these guidelines. For example, in some cases very specific error reports could be a security problem.
It might be useful to know what effect a try block has on the compiled code. It doesn't change the compiled instructions at all! (Of course, the corresponding catch block does, since it's like any other code.)
A try block creates an entry in the exception table associated with the method. This table has a range of source instructions counters, an exception type, and a destination instruction. When an exception is raised, this table is examined to see if there is an entry with a matching type, and a range that includes the instruction that raised the exception. If it does, execution branches to the corresponding destination number.
The important thing to realize is that this table isn't consulted (and has no effect on running performance) unless it's needed. (Neglecting a little overhead in the loading of the class.)
I've been told that there is some overhead in using the Java try-catch mechanism.
Absolutely. And there's overhead to method calls, too. But you shouldn't put all your code in one method.
Not to toot the premature optimization horn, but the focus should be on ease of reading, organization, etc. Language constructs rarely impact performance as much as system organization and choice of algorithms.
To me, the first is easiest to read.
No. The only thing that you should be considering is where you can reasonably handle the exception and what resources you need to reclaim (with finally).
This is premature optimization at its worst. Don't do it.
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" - Knuth.
there is very very little benefit to the 2nd method. after all if you can successfully open a file but not read from it, then there is something very wrong with your computer. thus knowing that the io exception came from the readLine() method is very rarely useful. also as you know, different exceptions are thrown for different problems anyway (FileNotFoundException, etc)
as long as you scope it with a 'logical' block, ie opening, reading, and closing a file in 1 go, i would go with the first method. it's much simpler to read and, especially when dealing with IO, the processor cycles used by the try-catch overhead would be minimal if any.
Putting the try blocks around the specific code that may throw an exception, makes it, in my opinion easier to read. You're likely to want to display a different message for each error and provide instructions to the user, which will be different depending on where the error occurs.
However, the performance issue that most people refer to is related to raising the exception, not to the try block itself.
In other words, as long as you never have an error raised, the try block won't noticeably affect performance. You shouldn't consider a try block just another flow control construct and raise an error to branch through your code. That's what you want to avoid.
The second method will generate a compiler error that reader may not have been initialized. You can get around that by initializing it to null, but that just means you could get an NPE, and there's no advantage to that.