Weishi Z
Weishi Z

Reputation: 1748

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:

  1. throw different exception from two methods.

    • In this case the methods are written by others and I have no control.
  2. 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.

Upvotes: 5

Views: 8974

Answers (5)

Elliott Frisch
Elliott Frisch

Reputation: 201527

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.
    }
}

Upvotes: 1

ps-aux
ps-aux

Reputation: 12174

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.

Upvotes: 6

Miserable Variable
Miserable Variable

Reputation: 28761

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.

Upvotes: 2

Andreas
Andreas

Reputation: 159215

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.

Upvotes: 1

Matt
Matt

Reputation: 455

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.

Upvotes: 1

Related Questions