Trying to handle an exception two time in Java - java

I am trying to handle an exception 2 times
The first is in the core of a defined method :
Class Class1 {
public int method (int a, String b) {
try {
System.out.println(a+" "+b.length());
}
catch (NullPointerException e) {
// TODO: handle exception
System.out.println("catch from the method");
}
finally {
System.out.println("finally from the method");
}
return 0;
}
}
and the second
is when I call this method in main and passing a null parameter to it :
public Class Class2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Class1 c = null;
try {
c = new Class1();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
c.method(1, null);
}
catch (Exception e) {
// TODO: handle exception
System.out.println("catch from the main");
}
finally {
System.out.println("finally from the main");
}
System.out.println("\nEnd of the main");
}
}
and the result is :
catch from the method
finally from the method
finally from the main
End of the main
And now my question is, why the catch block in the main was not executed?

Once you catch an Exception, it doesn't go any further, but you can throw it again. If you want your main to also see the exception you need to throw the exception again after it is caught. Try this:
public int method (int a, String b) throws NullPointerException{
try {
System.out.println(a+" "+b.length());
}
catch (NullPointerException e) {
// TODO: handle exception
System.out.println("catch from the method");
throw e;
}
finally {
System.out.println("finally from the method");
}
return 0;
}
Notice since there is a throw in the function now, you need to include it in the function definition
Edit: As stated by a couple of people, NullPointerException does not really need to be caught because it is an unchecked exception. This is because it is a subclass of RuntimeException.

You find many texts on the mechanics of throwing and catching exceptions. What I find more important is how to make best use of the exceptions concept.
This is not exactly an answer to your question, but maybe clarifies some concepts behind the situation at hand.
Rules of Thumb
If a method fulfilled its job, it should return normally. If it failed to do so, it should throw an exception instead of the normal return. The exception coming out of your method should contain information on the problem (most of the standard exceptions already do that quite well).
In a subordinate method, you normally shouldn't use try/catch. If something goes wrong (some exception arises inside your method), then your method typically can't complete its job, it should tell its caller by means of an exception, and the easiest way is to just let the exception ripple through.
In a top-level method (e.g. main, main-menu action, button-click action), catch all exceptions, inform the user (and maybe the administrator) and continue (if possible/appropriate).
If your method gets one exception (e.g. a NullPointerException) and wants to show a different one to its caller, catch the exception, create the desired new one, using the original one as cause, and throw this new exception. Personally, I try to avoid this "exceptions translation" as much as possible.
Use finally if you have to close some resource that you obtained inside the body, that would stay blocked for extended periods of time if not closed. Think of I/O streams, database connections/transactions and similar things. Don't do it just for memory allocation, that's the garbage collector's job.
If you follow these rules, you'll find that your code can concentrate on its main job, isn't cluttered with lots of error handling, and still is robust in case of exceptions.
Your Example
It all depends on the question "What's the job of Class1.method()?".
That might be "Print these two numbers". Then, when it gets the NullPointerException, it won't fulfill its job, so it shouldn't return normally, and instead exit with an exception, most easily by doing nothing (no try/catch at all) and just letting the exceptions framework do its automatic job. That will mean that its caller gets the original NullPointerException:
public int method (int a, String b) {
System.out.println(a+" "+b.length());
}
If the job of Class1.method() were "Print these two numbers, but only if there is a string", then you should catch the NullPointerException inside (or better, check with an if) and return normally ("I've done my job!"). Then Class2.main() should be satisfied with the non-printing in case of null, and have no reason to do any error handling after calling Class1.method(). If Class2.main() doesn't want that behaviour, it shouldn't call Class1.method() in that case.

Related

Java: How to propagate a "method exit" when tucking-in exceptions?

By "method exit" - I mean the actions in a method such as return or throw new... that the compiler considers the end of a method - if you could please tell me the accepted word for "method exit", I will edit the question
My problem is the following:
I do a lot of throw new RuntimeException(...
So, I decided to "tuck it in" as:
public static void quickRaise (String msg) { throw new RuntimeException(msg); }
And then I can reuse it.
(This will help me in the future to enhance the procedure around raising Runtime Exceptions and even
switch to a custom Exception class, without fishing in the code for exception throws)
However, where before I could write:
public MyType doSomething() {
try {
//...
return new MyType (parameter);
} catch (Exception e) {
throw new RuntimeException("msg")
}
}
And the compiler would correctly understand that "this method either exits by return or by throw" and therefore there are no logical "dead ends"
When I changed throw new RuntimeException("msg") to quickRaise("msg"), the compiler no longer considers my method "complete". It complains about a missing return statement, even though quickRaise is semantically equivalent to throw (or at least this is what I am trying to do!)
Let me try to reiterate the problem by a reproductive example (this will not compile, which is the problem):
public static void main(String[] args) {
System.out.println(doSomething());
}
public static String doSomething () {
try {
//... Some fun stuff going on here
return "Something";
} catch (Exception e) {
quickRaise("Could not find handshakes");
//throw new RuntimeException("If you uncomment this line, it will compile!");
}
}
public static void quickRaise (String msg) {
throw new RuntimeException(msg);
}
Your idea is highly inadvisable.
For example, this is just bad codestyle:
try {
someIO();
} catch (IOException e) {
throw new RuntimeException("Problem with IO");
}
The reason it's bad is that you have now obliterated the actual information about the problem. That information is locked into 5 separate parts of that exception you just caught: Its type (for example, FileNotFoundException, its message (e.g. "Directory /foo/bar does not exist"), its stack trace, its causal chain, and as throwables are objects, any particular extra detail for that particular kind of exception (such as the DB-engine-specific error coding for some SQLException).
Throwing this info away is silly.
All you'd need to do to fix this, is to add the cause:
} catch (IOException e) {
throw new RuntimeException("IO problem", e);
}
Now the IOException is marked as the cause of the exception you are throwing, which means in error logs you'll see it + the message + the stack trace of it + the stack trace of any causes it had as well.
All you need to do to make the compiler realize that the method ends here, is to throw it:
public static RuntimeException quickRaise(String msg) {
throw new RuntimeException(msg);
return null; // doesn't matter, we never get here
}
// to use:
throw quickRaise(msg);
But, as I explained before, this is a very bad idea.
Secondarily, having the idea of 'I just want to throw an exception and maybe later I want to replace the kind of exception I throw' also doesn't really work out: You need to pick a proper exception for the situation, therefore you cannot write a one-size-fits-all throw method in the first place.
Okay, so what do I do?
Primarily, learn to embrace throws clauses. If your method fundamentally does I/O (for example, the javadoc of it and/or the name makes that obvious, it is for example saveGame(Path p), or scanUserHome), then it should be declared to throws IOException.
If your method is an entrypoint (as in, it is the first point where your own code begins running), then your method should be declared to throws Exception. For example, your public static void main() method should throws Exception. Sometimes an entrypoint isn't main but something else (a webhandler routing hook for example), and sometimes backwards silly franeworks prevent you from doing that, but there tends to be a wrap functionality (such as } catch (Exception e) { throw new ServletException(e); }).
For exceptions which are both [A] fundamentally not part of the method's purpose, but more part of an implementation detail and [B] is very unlikely to go wrong and there's not much you can do other than hard crash if it would, then, yeah, rewrap as RuntimeException. There isn't a lot of point in ever changing this 'globally' for all such exceptions. At best you belatedly realize that failure is a bit more likely than you originally thought and either create a proper exception for it and document this behaviour. But that's, again, on a per-method basis, not something you can apply in blanket fashion.
Your approach is fundamentally at odds with the need for the compiler to see that the flow terminates at the throw statement.
I'd suggest having a utility method that just constructs an exception, which you then throw from the original point.
It's either than or put dummy returns after each call to quickRaise().

In Java catch block, how do you know which method/line throws the exception?

In try block, I want to execute two functions. If the first one failed then don't execute the second. I also want to print out which function failed.
See following code.
try {
a = func1();
b = func2(); //won't execute if a failed
}
catch (Exception e) {
//TODO: print a or b failed?
}
Does the language support this scenario naturally?
If not, is the following a good practice? (I cannot think of anything wrong about it. But it concerns me as I don't remember seeing any one using return in catch.)
try {
a = func1();
}
catch {
//print: a failed
return; //if a failed then skip the execution of b
}
try {
b = func2();
}
catch {
//print: b failed
}
EDIT:
Summary of comments:
throw different exception from two methods.
In this case the methods are written by others and I have no control.
e.printStackTrace() will print line number and function
I want to do more than just printing. More like, if a failed, execute the following code.
What you want is String methodName = e.getStackTrace()[0].getMethodName());
But this is hardly a good practice. The standard way is to log the exception using appropriate method in your logging framework or (if writing a console app, which is rarely the case with Java) to print it to the error or standard output or optionally to other PrintStream, for example using printStackTrace(printStream).
But in most cases you want to propagate exception to the upper layers and handle (or decide to not handle it) by the appropriate high level code. Catching exceptions like this leads to nasty bugs. Returning from catch black is also a very bad idea in 99% of cases because exception signalizes abnormal termination of the method while returning a value does not.
As dev-null wrote e.getStackTrace() can help. But note that the exception may not be thrown by func1 or func2 themselves but by some other method they call. So you need to go through all elements of the array until you hit func1 or func2.
Calling them in separate try blocks is definitely practiced but it can get cumbersome.
Logging the stack trace if an exception is thrown will inform you which line threw the exception. If the first line in the try/catch throws the exception, the next line will not be executed.
This will work:
String failedFunc = "func1";
try {
a = func1();
failedFunc = "func2";
b = func2(); //won't execute if func1() failed
} catch (Exception e) {
System.out.println("Func '" + failedFunc + "' failed: " + e);
}
Or course, if all you're doing is printing the error, then printing the stack trace will show you exactly where it failed. The above code is however useful if you need the value of failedFunc without a full stack trace.
As I said in the comments, you can use e.printStackTrace() to determine the cause of the Exception. Since you expressed a desire for different behaviors then you have a few options. You could write two local functions to decorate your func1 and func2 calls with custom Exceptions. Something like,
class Func1Exception extends Exception {
public Func1Exception(Exception e) {
super(e);
}
}
class Func2Exception extends Exception {
public Func2Exception(Exception e) {
super(e);
}
}
Then you can write the local functions like
private static Object func1Decorator() throws Func1Exception {
try {
return func1();
} catch (Exception e) {
throw new Func1Exception(e);
}
}
private static Object func2Decorator() throws Func2Exception {
try {
return func2();
} catch (Exception e) {
throw new Func2Exception(e);
}
}
Then you can handle them however you wish,
try {
a = func1Decorator();
b = func2Decorator(); // this still won't execute if a failed
} catch (Func1Exception e) {
// a failed.
} catch (Func2Exception e) {
// b failed.
}
If you want func2 to run even when a fails you could use a finally block,
try {
a = func1Decorator();
} catch (Func1Exception e) {
// a failed.
} finally {
try {
b = func2Decorator(); // this will execute if a fails
} catch (Func2Exception e) {
// b failed.
}
}

Can someone help me understand the working of try-catch block in java?

This might be a really dumb question to most of you here, really sorry about that. I am new to java and the book i am reading didn't explain the working of an example in it.
public class CrazyWithZeros
{
public static void main(String[] args)
{
try
{
int answer = divideTheseNumbers(5, 0);
}
catch (Exception e)
{
System.out.println("Tried twice, "
+ "still didn't work!");
}
}
public static int divideTheseNumbers(int a, int b) throws Exception
{
int c;
try
{
c = a / b;
System.out.println("It worked!");
}
catch (Exception e)
{
System.out.println("Didn't work the first time.");
c = a / b;
System.out.println("It worked the second time!");
}
finally
{
System.out.println("Better clean up my mess.");
}
System.out.println("It worked after all.");
return c;
}
}
I can't figure out where the control will go after another exception is generated in catch block in divideTheseNumbers() method ?
Any help will be appreciated !
Output for your program will be
Didn't work the first time.
Better clean up my mess.
Tried twice, still didn't work!
Didn't work the first time. - because of the catch block in divideTheseNumbers
Better clean up my mess. - because of the finally block in divideTheseNumbers
Tried twice, still didn't work! - because of the catch block in the main method.
In general when a exception is thrown from a method and if is not in a try block, it will be thrown to it's calling method.
There are two points to note :
1) Any exception that is not in a try block will be just thrown to
it's calling method(even if it is in a catch block)
2) finally block is always executed.
In your case, you are getting the second exception in catch block, so it will be thrown. But before exiting any method it will also execute finally block(finally block is always executed). That is why Better clean up my mess is also printed.
Some points regarding exception handling:
1. Place your code that may causes exception inside the try{} block.
2. Catch the appropriate exception using the catch block.
3. While catching exception it's better use more specific type exception instead of catching the generic exception like. For example you catch the Exception, in this case you may catch the more specific type exception ArithmeticException.
4. finally block always executed, even though you use return statement in catch or try block.
5. A method either throws or catch an exception. If a method catch an exception then for it is not required to throws the exception.
6. All exception need not to be handled by using catch-block. We can avoid the try-catch block for the unchecked exception like - ArithmeticException,NullPointerException, ArrayIndexOutOfBoundsException. See here for more.
You may also check the tutorial for learning more about exception handling.

what is the effect that explicits the "throw exception" in the method signature

--the effects of case 1 and 2 are the same, why need to add the exception declaration in method signature?
//case 1
public void doSomething() throws Exception {
//do Something
}
public void Caller() {
try {
doSomething();
} catch (Exception e) {
//handle the exception
}
}
//case 2
public void doSomething() {
//do Something
}
public void Caller() {
try {
doSomething();
} catch (Exception e) {
//handle the exception
}
}
reference:
what is the use of throws Exception
The throws declaration is used to declare which checked exceptions your method throws.
For instance, if I write this code:
public void doSomething() throws SQLException {
}
any code that calls this method must have a try/catch block for SQLException, Exception, or Throwable... or it can have its own throws declaration for one of those 3.
In this case, there is no difference, except that you're alerting the compiler to an exception that you're not going to be throwing.
It's also a bad idea to catch throw "Exception" - in both cases, you want to deal a particular exception that has a particular meaning. When you're catching, the only reason to use a try block is if you expect a particular exception, so you should catch that one. This way, if some unexpected exception comes up, you don't try to handle it the wrong way. (instead, your program fails, and you know there's a condition you have to deal with) When you're throwing, you want to throw a particular exception, either one you make up, or a standard one that has a known meaning, so the calling function knows what to deal with. For example, if your doSomething might throw an ArrayIndexNotFoundException if the widgets are not frobnicated, you might want to catch the ArrayIndexNotFoundException and throw a WidgetNotFrobnicatedException. Any time you throw an exception, your javadoc should specify exactly what circumstances will trigger that issue, so the user of your code has a chance to address this possible failure.
(there is one circumstance when I can see catching Exception, and that's if you want to fade to some graceful halt if things go wrong unexpectedly - in that case, in your catch block you'd log the issue, possibly alert a developer, and throw up some sort of "Sorry, error number 3542 has occurred, please restart the program" message.)
If your doSomething method, has the chance to throw an exception and you don't want to catch it, you should add this throws Exception on the method.
Unless it's an exception that you want to handle immediately in that method, it's good practice to use throws [specific Exception] so that the exception can be handled further up in the code.
It's somewhat commonplace to have a generic Throwable catch at the top that "gracefully crashes" in case something goes wrong.

How to make a try-catch block that keeps on calling a method on an object until there are no more exceptions to catch

Basically iterating through a list and,
- Invoke method on first object
- Catch the first exception (if any); if there are no more exceptions to catch, return normally. Otherwise, keep on invoking method until all exceptions are caught.
- Move on to next object.
I can iterate through each object, invoke the method, and catch one exception but I do not know how to continuously invoke the method on it and keep on catching exceptions.
This is similar to the other answers, but without the flag, which seems like clutter to me. I don't really understand the question though, so I'm just throwing it out there in case it is useful.
for (Item item : items) {
while (true) {
try {
item.doSomething();
break;
} catch (MyException ex) {
log.warn("Something failed.", ex);
}
}
}
This approach hinges on the operation of the unlabeled break statement, which completes abruptly and then exits the enclosing while statement normally.
Based on subsequent comments, I think there is some confusion about what it means when there are multiple exceptions declared to be thrown by a method.
Each invocation of a method can be terminated by just one exception being thrown. You can't somehow resume invocation where it left off, and handle subsequent exceptions.
So, if a method throws multiple exceptions, catch a common ancestor, and move on. For example, if a method throws java.io.EOFException or java.nio.channels.ClosedChannelException, you could simply catch java.io.IOException since it is a common ancestor. (You could also catch java.lang.Exception or java.lang.Throwable for the same reason.) Invoking the method again under the same conditions won't get you any further.
If you want to attempt to invoke the method on each object, even if some fail, use this:
for (Item item : items) {
try {
item.doSomething();
} catch (Exception ex) { /* This could be any common ancestor. */
log.warn("Something failed.", ex);
}
}
If you're talking about dealing with a single method call that will throw more than one exception, it can't be done -- no matter how many times you call the method, it will keep on throwing the first exception. You can't go back into the method and keep running from there; after throwing one exception, it's all over.
But if you're talking about a method that sometimes throws exceptions and sometimes doesn't, try something like this:
boolean thrown = false;
do {
try {
thrown = false;
method();
}
catch (Exception e) {
thrown = true;
// Handle as you like
}
} (while thrown);
This is what I understand.
You have an object's method which may throw a number of exceptions.
What you want to do is to catch them all and continue with the next object in the list.
Is that correct?
So, that would be:
for( YourObject o : yourList ) {
try {
o.thatMethod();//invoke that risky method
} catch( SomeExceptionClass sec ) {
// Do something with that exception
} catch( SomeOtherExceptionClass soec ) {
// Do something with that exception
} catch( YetAnotherxceptionClass yaec ) {
// Do something with that exception
} catch( OtherUnRelatedException oue ) {
// Do something with that exception
}
}
When you do this, if the invocation of thatMethod() throws an exception and that exception is listed in the catch section, the execution flow will jump to that exception and after it will continue to the normal flow ( which is the for loop and will continue with the next object )
I hope this is what to need. For more information read: The catch block in the Java Tutorial section Essential classes
I'm assuming that you are trying to performs some kind of validation to the items in a list, where the validation errors are reported by throwing exceptions. I'm also assuming that you are trying to collect all of the validation errors.
The simple answer is that this problem cannot be solved using this approach. To understand why, take a look at this:
boolean exceptionCaught = false;
do {
try {
item.doSomething();
} catch (MyException e) {
exceptionCaught = true;
}
} while (exceptionCaught);
This fails because each time you call item.doSomething() it is going to throw an exception at exactly the same place. The net result is an infinite loop.
The best you can do with this approach is to capture the first exception for each item in the list.
So how can you achieve what you are trying to achieve? The answer is that you have to change the validation code to use some other way to report errors than throwing exceptions. For example, you could change:
class Item {
...
void validate() {
if (noHat) {
throw new MyException("bad hat");
}
if (noPants) {
throw new MyException("world-wide pants");
}
}
}
to something like this:
class Item {
...
void isValid(List<MyException> errors) {
boolean ok = true;
if (noHat) {
errors.add(new MyException("bad hat"));
ok = false;
}
if (noPants) {
errors.add(new MyException("world-wide pants"));
ok = false;
}
return ok;
}
}
Messy huh! You could sugar this in various ways, but this style of error reporting is always going to be more complicated. But I don't think there is a practical way to avoid the messiness AND capture ALL of the validation errors.

Categories

Resources