Let's say we have nested methods A, B and C like below:
public void A(){
try{
B();
}
catch(Exception e){
log.error(e);
}
}
public void B(){
C();
}
public void C(){
try{
some_stuff();
}
catch(Exception e){
log.error(e)
}
}
Since I catch the exception at C() and handle it with only logging, and there isn't any catch in B(), do I catch the exception at A()?
Or should I throw the exception at C() and add a try catch at B() to be able to handle it in A()?
When you do
public void C(){
try{
some_stuff();
}
catch(Exception e){
log.error(e)
}
}
This will handle the exception at this point. You will log it and disregard the exception. If you want to log and propagate it up, you need to re-throw it from the catch clause.
Since Exception is checked (as far as I remember) you need to change the method signature to indicate that you are throwing this from C.
At B you don't need to handle it, you can just change the method signature to indicate the method throws Exception.
Read more on Java checked vs unchecked exceptions for example here enter link description here
Finally if you want to propagate to A the code will look like this:
public void A(){
try{
B();
}
catch(Exception e){
log.error(e);
}
}
public void B() throws Exception{
C();
}
public void C() throws Exception{
try{
some_stuff();
}
catch(Exception e){
log.error(e)
throw e;
}
}
You are handling the exception in the catch block, therefore it will not be further propagated to the caller. This is independent of whether you are logging it or doing anything else with it. If you want want to propagate it to the caller, you would need to re-throw it:
[...]
catch (Exception e) {
// do something
throw e;
}
How you handle exceptions depends on the design of your code.
Related
If I have multiple functions in a function which are throwing exceptions what's the best way of handling them if they depend on each other?
With depending on each other I mean that if something throws an exceptions the code after the function which threw the exception should be skipped.
I figured out three ways to do this:
Exception nesting
public void parent() {
someFunction();
}
public void someFunction() {
try {
function1();
try {
function2();
...
} catch (Func2xception e) {
System.out.println("Function 2 failed!");
}
} catch (Func1Exception e) {
System.out.println("Function 1 failed!");
}
}
Return on exception
public void parent() {
someFunction();
}
public void someFunction() {
try {
function1();
} catch (Func1Exception e) {
System.out.println("Function 1 failed!");
return;
}
try {
function2();
} catch (Func2xception e) {
System.out.println("Function 2 failed!");
return;
}
...
}
Add exceptions to method signature
public void parent() {
try {
someFunction();
} catch (Func1Exception e) {
System.out.println("Function 1 failed!");
} catch (Func2Exception e) {
System.out.println("Function 2 failed!");
} ...
}
public void someFunction() throws Func1Exception, Func2Exception {
function1();
function2();
...
}
I sometimes use all of them together and that's a mess. Are there any good practices on how to handle situations like this?
The way to use depends on whether the exceptions should be handled by the client of the someFunction() method or else caught and handled as soon as they happen, that is, inside the someFunction() method.
In the exception nesting case, the nesting is not required.
You can use a single try statement and place the two calls that may generate the exceptions in it.
If an exception occurs in one of the two invoked methods, you finish in one of the catch statements and so the second method is executed only if the first one has not thrown the caught exception.
It produces exactly the same result than your code but with a single try and without nesting that is less readable.
public void someFunction() {
try {
function1();
function2();
...
} catch (Func1Exception e) {
System.out.println("Function 1 failed!");
}
catch (Func2xception e) {
System.out.println("Function 2 failed!");
}
}
This way of doing is suitable if you have some other instructions after the catch statements and you want them to be executed even if one of the expected exceptions was caught.
The return on exception case manifests a close enough problem.
It may be refactored with a single try :
public void someFunction() {
try {
function1();
function2();
...
} catch (Func1Exception e) {
System.out.println("Function 1 failed!");
return;
}
catch (Func2xception e) {
System.out.println("Function 2 failed!");
return;
}
}
...
}
This way of doing is suitable if you have some other instructions after the catch statements and you don't want them to be executed if one of the expected exceptions was caught.
Nevertheless for these two cases, if the exception handling is the same for the two exceptions (Func1Exception and Func2xception), you could group them in a single catch statement :
public void someFunction() {
try {
function1();
function2();
...
}
catch (Func1Exception | Func2xception e) {
System.out.println("Function 1 or 2 failed!");
}
}
At last, the add exceptions to method signature case makes sense only if the exceptions should be handled by the client of the method.
You can catch multiple exceptions in one catch clause, starting from Java 7 I believe.
try {
...
} catch(IOException | IllegalArgumentException | SomeOtherException e) {
...
}
The below statement is from thinking in java, "A derived-class constructor cannot catch exceptions thrown by its base-class constructor." But I am able to catch it. Can Anyone explain where I went wrong?
class Base {
Base() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
class Derived extends Base {
Derived() throws CloneNotSupportedException, RuntimeException {}
public static void main(String[] args) {
try {
Derived d = new Derived();
}
catch(CloneNotSupportedException e) {
e.printStackTrace();
}
catch(RuntimeException re){}
}
}
output:
java.lang.CloneNotSupportedException
at Base.<init>(Coffee.java:4)
at Derived.<init>(Coffee.java:9)
at Derived.main(Coffee.java:14)
You are not catching anything in the derived class's constructor. You catch the exceptions in the main method. Therefore you are not contradicting the quote you posted.
Here's how your derived-class constructor would have to look in order to catch an exception from the base-class constructor:
Derived() {
try {
super();
} catch (CloneNotSupportedException e) {
System.out.println("We have indeed caught an exception from the "+
"base-class constructor! The book was wrong!");
}
}
Try it and see what comes out.
I have a lot of custom exceptions that I'm throwing in a specific cases in the code, and I'd like to have one catch block at the bottom of the method to handle them all.
All the exceptions are children of the Exception class CribbageException, so I'd like to have:
public void myMethod(){
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
But I'm getting a catch without try error.
Is there any way to use this type of exception handling?
Wrap all the throws inside a single try.
public void myMethod(){
try {
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
I have a constructor which calls another constructor in the same class. The problem is I want to catch Exceptions and throw them onwards to the method that called the first constructor. Yet Java doesn't allow this as the constructor call must be the first statement in the constructor.
public Config(String fn) throws IOException, ExcFormattingError {
theFile = fn;
try { cfRead(); }
catch(FileNotFoundException e) {
//create a new config with defaults.
theConfig = defaultConfig();
create();
} catch (IOException e) {
throw new IOException(e);
} catch (ExcFormattingError e) {
throw new ExcFormattingError();
}
fixMissing(theConfig);
}
public Config() throws IOException, ExcFormattingError {
try {
//Line below is in error...
this("accountmgr.cfg");
} catch (IOException e) {
throw new IOException(e);
} catch (ExcFormattingError e) {
throw new ExcFormattingError();
}
}
If someone could explain how I could do this that would be good. A bonus would be knowing why the language has to behave this way, because that is always interesting.
You don't need those try-catch block inside the constructor (in fact, you can't write it there, as you already figured out). So, change your constructor to:
public Config() throws IOException, ExcFormattingError {
this("accountmgr.cfg");
}
In fact the catch block in your constructor was hardly doing anything productive. It was just re-creating an instance of the same exception, and throwing it. That is really not needed given the fact that, if the exception is thrown, it will automatically propagated to the caller code, where you can handle the exception.
public void someMethod() {
Config config = null;
try {
config = new Config();
} catch (IOException e) {
// handle it
} catch (ExcFormattingError e) {
// handle it
}
}
Having said that, it is rarely a good idea to throw a checked exception from the constructor, even worse handling them in the caller code.
If the exception is thrown, and you handle it in the calling method. Then you are simply ignoring the fact that your instance is not completely initialized. Proceeding with that instance further will result in some unexpected behaviour. So, you should avoid it really.
I have a basic question in Java:
I have two methods: functionA & functionB. functionA calls functionB, and functionB rise an exception. The call to functionB is in try scope of functionA.
Now I also want that functionA will go to it catch scope.
There is any way to do that?
If an exception is thrown in methodB and you catch it, one way to propagate it to methodA is to rethrow it:
void methodB() throws SomeException {
try {
//Something that can throw SomeException
} catch (SomeException e) {
//rethrow e
throw e;
}
}
void methodA() {
try {
methodB();
} catch (SomeException e) {
//this block will run if methodB throws SomeException
}
}
But if you need that, you probably should not catch the exception in methodB at all and just let it propagate automatically to methodA:
void methodB() throws SomeException {
//Something that can throw SomeException: don't catch it
}
void methodA() {
try {
methodB();
} catch (SomeException e) {
//this block will run if methodB throws SomeException
}
}
Actually, that is how it works usually, provided that functionB doesn't catch the exception itself. Exceptions, when thrown, bubble up the call stack until a matching catch block is found.
Not sure if this is what you want
void functionB() throws MyException {
try{
.....
}Catch(MyException e){
//do something here;
throw e;
}
}
void functionA() {
try {
functionB();
} catch (MYException e) {
//do something else to A here
}
}