I guess there isn't necessarily a 'right' answer to this, perhaps it's more a question of style but I often find myself wondering how to structure try/catch blocks.
For example take the two methods outlined in my hypothetical piece of code below (purely illustrative), I have a method that throws exceptions that I call multiple times but require different handling depending on which call it is. Similarly there could be different types of exception thrown with different handlers.
private Object exceptionMethod() throws Exception {
throw new Exception("Something bad happened");
}
public void useMethodSequentialHandlers() {
Object o1; // Must be declared in a wider scope than where it is used
try {
o1 = exceptionMethod();
} catch (Exception ex) {
// Assume we cannot continue after this exception so we'll return or
// rethrow to exit the method
return;
}
Object o2; // Must be declared in a wider scope than where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
o2 = exceptionMethod();
// Here we would use the objects in some manner
boolean equal = o1.equals(o2);// Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this exception
continue;
}
}
}
As I see it the advantage of having the try/catch blocks in a sequential order is that it is clearer to the reader exactly at what point I'm responding to the exception so perhaps there is better code clarity.
The disadvantages would be that we have exception handling littered around various places in the method and we have variables declared in a wider scope than required (is this a bad thing?).
Alternatively:
public void useMethodNestedHandlers() {
try {
Object o1 = exceptionMethod(); // Can be declared inside scope where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
Object o2 = exceptionMethod(); // Can be declared inside scope where it is used
// Here we would use the objects in some manner
boolean equal = o1.equals(o2); // Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this
// exception
continue;
}
}
} catch (Exception ex) {
// Assume we cannot continue after this exception so we'll return or
// rethrow to exit the method
return;
}
}
Here we keep exception handling logic together and variables are declared within the scope they're used. However to me the exception handling logic seems less clear as it is further from it's point of origin.
Does anyone have an opinion on which would be better or am I just worrying about pointless minutiae and should just get on with my job? :-)
Thanks
I would prefer both depends the condition.
Case 1
Object obj;
try {
// do something
} catch (Exception e) {
obj = default_obj; // assign default object
}
try {
// do something either with specific or default object
} catch (Exception e) {
// handle exception
}
Here even if the first try catch fails , proceed the action with default value
Case 2
try {
Object obj;
// acquire object
// do something only if acquire object is successful
} catch (Exception e) {
// handle exception
}
Here do not proceed further when acquire object isn't successful.
Here it is way of handling exception is more of a necessity than a style.
I believe that in all cases were the answer does not clearly arise from technical analysis one should ignore the initial development work and study the future of the code.
To this end I would advise the first method as the best choice unless there is a real technical reason to choose the second.
In summary:
If there is no technical difference between two styles, consider the future reader of your code and make it as obvious as possible.
The beauty of exceptions is that you don't have to handle them where they occur. That's why you should in fact use your second style, but without the outer try-catch:
public void useMethodNestedHandlers() {
Object o1 = exceptionMethod(); // Can be declared inside scope where it is used
// Do something that requires o1
for (int i = 0; i < 100; i++) {
try {
Object o2 = exceptionMethod(); // Can be declared inside scope where it is used
// Here we would use the objects in some manner
boolean equal = o1.equals(o2); // Just a pointless example
// to show that both objects
// are required
// Assume the method does a load of stuff down here
} catch (Exception ex) {
// Assume we can continue to the next iteration after this
// exception
continue;
}
}
}
Code for the happy-day scenario and let someone else worry about failures. That's the way to achieve separation of concerns: usually all failures are treated by the same piece of code and catching too early breeds duplicated code.
the code should be 1) correct, 2) readable. usually all irrecoverable exception should be handle in highest layer of application (or not at all). that means they should be properly displayed to the user. all recoverable exceptions should be handle 'as high' as possible. i advise to use as few try-catch statements as possible
Related
I want to avoid this ugly pattern:
Long foo = null;
Double bar = null;
try {
foo = Long.parseLong(args[0]);
bar = Long.parseLong(args[0]);
} catch (NumberFormatException e) {
System.out.println(USAGE);
System.exit(1);
}
doSomethingWith(foo, bar);
I know I can move the initialisations and doSomethingWith into the try block, but imagine:
doSomethingWith is actually several lines of conditional logic, many method calls, statements etc.
I don't want to be nesting blocks unnecessarily deeply
I want to avoid accidentally catch unexpected NumberFormatExceptions thrown from doSomethingWith.
I find the = null and above quite ugly, as well as the use of classes instead of primitives. This ugliness makes me suspect there's a better way to write this code.
My first vision is of course
long foo;
double bar;
try {
foo = Long.parseLong(args[0]);
bar = Long.parseLong(args[0]);
} catch (NumberFormatException e) {
System.out.println(USAGE);
System.exit(1);
}
doSomethingWith(foo, bar);
but we all know Java throws a couple variable might not have been initialized errors when you try to build that.
What's a better design pattern for this kind of problem? "Better" meaning (for me) does all of this
avoids the weird = null
avoids unnecessary class wrappers around primitives
doesn't nest deeply into the try block
doesn't catch/hide exceptions it wasn't meant to
If this is not possible, or if my concept of "pretty" code is wrong, please convince me and show the best that can currently be used.
The oddity here is that the compiler doesn't know that System.exit(1); will never return. If it knew that, it would be happy.
So all you need to do is give it something that it knows won't let you get from the catch block to after the try/catch. For example:
try {
foo = Long.parseLong(args[0]);
bar = Long.parseLong(args[0]);
} catch (NumberFormatException e) {
System.out.println(USAGE);
System.exit(1);
throw new RuntimeError("Make sure the end of the catch block is unreachable");
}
If you need to do this often, you might want to write a helper method, and throw the result of it (which you'll never use). That way you still only have a single line of code for "I want to quit now".
try {
foo = Long.parseLong(args[0]);
bar = Long.parseLong(args[0]);
} catch (NumberFormatException e) {
System.out.println(USAGE);
throw HelperClass.systemExit(1);
}
...
public class HelperClass {
public static RuntimeException systemExit(int exitCode) {
System.exit(1);
throw new RuntimeException("We won't get here");
}
}
Another option I've used quite a bit is to define a sort of "User error" exception. You can then catch that at the top level (in main), print any message and possibly display the usage. That way:
You can unit test user errors (unit testing System.exit is at least more awkward)
You have centralized handling of "what do I want to do if the user made an error" rather than including System.out.println(USAGE) in multiple places
You don't run into this definite assignment issue
So your code would then be:
try {
foo = Long.parseLong(args[0]);
bar = Long.parseLong(args[0]);
} catch (NumberFormatException e) {
throw new UserInputException("foo and bar must both be valid integers");
}
I couldn't resist! This is another cleaner (but longer) solution.
// SomeModel(a: long, b: long)
public static Optional<SomeModel> validate(final String[] args) {
try {
// Probably some other null checks and things like that here also
return Optional.of(new SomeModel(Long.parseLong(args[0]), Long.parseLong(args[1])));
} catch (final NumberFormatException e) {
System.out.println(USAGE);
System.exit(1);
}
return Optional.empty(); // Or use some other "defaults" for that model
}
public static void doSomethingWith(final SomeModel input) { // ...signature changed!
// Do your stuff here
}
public static void main(final String[] args) {
validate(args).ifPresent(it -> doSomethingWith(it));
}
This flow is more clear but it's more verbose. The validations are separated and there is nothing else to do to please the compiler. Having to mode the return might be a drawback, but it pays off later on.
I have 2 examples:
void terminate(String x) {
System.exit(0);
}
void x (long y) {
if(y == null) {
terminate();
}
//code
}
.....
x(null); //Don't want that
This example seems to work. I want to make sure that long y is not null. I might do this instead:
void x (long y) throws NullPointerException {
//code
}
...
try {
x(null);
} catch (NullPointerException e) {
e.printstacktrace();
}
What would the difference in performance be? In such example, it might not be visible, but in a complex program, would it matter? Should I get into practice of exceptions instead of if then?
Use exceptions for exceptional circumstances, when things happen that youdid not expect and where nothing sensible can be done to recover.
Otherwise, use if-then and maybe return a status code.
In terms of performance, exceptions create a huge overhead compared to returns. Calling a method and catching an exception if it didn't work is verbose and annoying.
void myOperation() {
step1();
step2();
step3();
}
In this example, exceptions are preferable for when any of the steps fails, the entire operation fails anyways, so I prefer not having to deal with any of this.
void myOperation(String number) {
int n;
try {
n = Integer.parse(number);
} catch (NumberFormatException e) {
n = DEFAULT;
}
doThings(n);
}
In this case, having to catch the exception is annoying because I kind of expect the string to be invalid and have a reasonable alternative. The exception makes the code slow and verbose.
What would the difference in performance be?
Version with exception definitely will works slower and will have overhead of processing exceptions, creating objects, filling stack traces and so on.
In such example, it might not be visible, but in a complex program,
would it matter? Should I get into practice of exceptions instead of if then?
In complex programs none use this kind of processing possible null pointer exceptions, and it's actually anti-pattern in java, so if you whant be save with null you should you kind of not null check like if(x!=null) or assert.
Also I advice you read more about exceptions in java and differences between checked/unchecked exceptions and so on.
PS here is good topic about null checks.
Consider this code:
final MyClass myObject;
try {
myObject = new MyClass(...)
} catch (MyClassException){
// terminate
System.exit(1);
}
myObject.doSomething();
The problem is that the Netbeans editor / parser thinks that .doSomething() could be called on an unitialised object which, of course, is not the case.
Is there an normal / standard pattern for circumventing this? I could call into a function but would rather not do that. I'd also rather not enclose the whole block in the try catch block since nothing else throws MyClassException
I'm not (yet ;-) ) an expert on Java grammar and patterns so am hope I'm missing something obvious.
You initialize your object in try block, which may throw exception, leaving object uninitialized.
In your catch block, you stop your program, but System.exit(1) does not stop method execution, instead, it terminates currently running JVM - and for compiler it's just another method you call if an exception is thrown.
return actually stops method execution - so no code beyond return; is reached.
You can modify your catch block as following:
catch (MyClassException){
// terminate
System.exit(1);
return;
}
Compiler won't complain about myObject not being initialized this way.
EDIT
NB: if you put myObject.doSomething(); in finally block compiler WILL complain, since finally is executed even after return.
finally {
// compiler error
myObject.doSomething();
}
The case is that outside the try/catch block you try to call a method on a possibly not instantiated object. That is because the try/catch block may throw exceptions so the object is not created, therefore in this case you will not have an object when you try to call the doSomething() method on it.
If you include the method call in the try/catch block, it will work.
You can find related information here:
Java Tutorials: Lesson: Exceptions
Netbeans editor / parser thinks that .doSomething() could be called on an unitialised object which, of course, is not the case.
You are wrong here. You are in fact trying to initialize the variable. The compiler doesn't "trust" in the initialization and the reason is simple: it could throw an exception, which you could catch but not throw a new RuntimeException() or make a System.exit(1). For example:
try {
myObject = new MyClass(...)
} catch (MyClassException e){
// hey I catch this but do nothing lmao yolo
e.printStackTrace();
}
myObject.doSomething();
you could catch the exception, print the stacktrace and continue the program, and the consequence would be a NullPointerException.
This is the best I can do:
final MyClass myObject;
{
MyClass local = null;
try {
local = new MyClass(...)
} catch (MyClassException){
// terminate
System.exit(1);
}
myObject = local;
}
myObject.doSomething();
The problem is that the Netbeans editor / parser thinks that .doSomething() could be called on an unitialised object which, of course, is not the case.
It is the case: nothing prevents you from using a SecurityManager which will forbid System.exit() from exiting the JVM. In that situation, the next statement could be executed.
From a Java grammar perspective, the compiler needs to prove that myObject is definitely assigned when you call myObject.doSomething();.
The JLS specifies the situations in which this can be done. In particular, the only statements that can be used to determine that the next instruction(s) will not be executed are break, continue, return, and throw. So the compiler is not allowed to consider that System.exit(1); will prevent the next statement from being executed.
The point of the final variables and members is to always be initialized. Although your code will never call doSomething, it will leave the final field undefined. This becomes an issue if you add a finally clause to the try-catch block - you may enter the finally clause when exception occurs and the myObject will not be available, which the compiler must avoid.
final MyClass myObject;
try {
myObject = new MyClass(...); // constructor may throw exception
} catch (MyClassException){
// terminate
System.exit(1);
} finally {
// what does myObject point to now, if the constructor threw exception?
}
myObject.doSomething();
A quick solution is to move the doSomething call in the try block:
final MyClass myObject;
try {
myObject = new MyClass(...);
myObject.doSomething();
} catch (MyClassException){
// terminate
System.exit(1);
}
This should work fine as long as doSomething does not also throw a MyClassException. If it throws such exception, you probably need to differentiate the case whether it came from the constructor or the method (if of course this matters to your logic).
//Assume list1 and list2 are populated with states as 2
foo (List<Class1> list1, List <Class1> list2) {
boolean error = false;
try {
operate on list1
} catch (Exception e) {
error = true;
//Modify list1 objects to state 1
}
try {
operate on list2
} catch (Exception e) {
error = true;
//Modify list2 objects to state 1
}
//What are the problems and what is the best practice for this
if (error)
throw new Exception(…); //How should i really rethrow the exception
}
The main improvement I'd make is to store all exceptions that occur and make them available somehow, somewhere. Otherwise, it seems fine.
To the skeptical, it's not really abnormal to want to complete some work even when an exception happens. Batch processing is a pretty typical case.
Nothing technically wrong with it, other than getting the throws clause correct, etc. You could even save one of the caught exceptions and re-throw it.
Not clear why you'd want to do this, but I've done weirder.
In Java, what is the difference (in term of performance) between:
for (int i = 0; i < count; i++) {
try {
// code that throws Exception
} catch (Exception e) {
e.printStackTrace();
}
}
and
try {
for (int i = 0; i < count; i++) {
// code that throws Exception
}
} catch (Exception e) {
e.printStackTrace();
}
In your first version the loop continues if it hits an exception, in the second version the loop continues after the catch block. That is the most important difference of those code snippets.
You can use both, but it all depends on what you want it to do. If you want to continue the execution after the loop finishes once then you do it the first way. If you want to catch an exception then stop executing the loop then you do the second. Performance wise it all depends on what you want to do with it.
The main difference is that in the first snippet of code, even if there is an exception thrown from the try block and it is caught execution of the for loop continues. In the second snippet if an exception is thrown then the for loop is exited. This is because the whole loop is within the try block.
No I'm quite sure there's absolutely no difference from a point of performance here (ignoring the obvious fact about the loop). In both cases you create exactly one entry in the exception table - only the PC values (ie in which range the exception is valid) will be a bit different.
ie if you assume the following is the exception table the only thing that'll change are the x, y and z values..
Exception table:
from to target type
x y z <Class java.lang.Exception>
Since you asked about performance in the two versions of code, I am reminded of "Practical Java" (Addison-Wesley 2000) which recommends in Praxis 23: Place try/catch blocks outside of loops. The reason involves running the code on a JVM with the JIT compiler turned off. In that case, the lack of run-time JIT optimizations results in extra branches in the opcode, leading to reduced performance. You can read JIT docs of 2014 here: http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
Besides the difference in your logic with the continuing for. It's no noticeable difference between
try {
lots of stuff which might not throw any exception
something that throws exception
} catch (Exception e) {
}
and
lots of stuff which might not throw any exception
try {
something that throws exception
} catch (Exception e) {
}