Many people say that checked exceptions (i.e. these that you should explicitly catch or rethrow) should not be used at all. They were eliminated in C# for example, and most languages don't have them. So you can always throw a subclass of RuntimeException (unchecked exception).
However, I think checked exceptions are useful - they are used when you want to force the user of your API to think how to handle the exceptional situation (if it is recoverable). It's just that checked exceptions are overused in the Java platform, which makes people hate them.
Here's my extended view on the topic.
As for the particular questions:
Is the
NumberFormatExceptionconsidered a checked exception?
No.NumberFormatExceptionis unchecked (= is subclass ofRuntimeException). Why? I don't know. (but there should have been a methodisValidInteger(..))Is
RuntimeExceptionan unchecked exception?
Yes, exactly.What should I do here?
It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs, in most of the cases, you should choose one of these:
- log it and return
- rethrow it (declare it to be thrown by the method)
- construct a new exception by passing the current one in constructor
Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I?
It could've been. But nothing stops you from catching the unchecked exception as well.Why do people add class
Exceptionin the throws clause?
Most often because people are lazy to consider what to catch and what to rethrow. ThrowingExceptionis a bad practice and should be avoided.
Alas, there is no single rule to let you determine when to catch, when to rethrow, when to use checked and when to use unchecked exceptions. I agree this causes much confusion and a lot of bad code. The general principle is stated by Bloch (you quoted a part of it). And the general principle is to rethrow an exception to the layer where you can handle it.
Answer from Bozho on Stack OverflowVideos
Many people say that checked exceptions (i.e. these that you should explicitly catch or rethrow) should not be used at all. They were eliminated in C# for example, and most languages don't have them. So you can always throw a subclass of RuntimeException (unchecked exception).
However, I think checked exceptions are useful - they are used when you want to force the user of your API to think how to handle the exceptional situation (if it is recoverable). It's just that checked exceptions are overused in the Java platform, which makes people hate them.
Here's my extended view on the topic.
As for the particular questions:
Is the
NumberFormatExceptionconsidered a checked exception?
No.NumberFormatExceptionis unchecked (= is subclass ofRuntimeException). Why? I don't know. (but there should have been a methodisValidInteger(..))Is
RuntimeExceptionan unchecked exception?
Yes, exactly.What should I do here?
It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs, in most of the cases, you should choose one of these:
- log it and return
- rethrow it (declare it to be thrown by the method)
- construct a new exception by passing the current one in constructor
Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I?
It could've been. But nothing stops you from catching the unchecked exception as well.Why do people add class
Exceptionin the throws clause?
Most often because people are lazy to consider what to catch and what to rethrow. ThrowingExceptionis a bad practice and should be avoided.
Alas, there is no single rule to let you determine when to catch, when to rethrow, when to use checked and when to use unchecked exceptions. I agree this causes much confusion and a lot of bad code. The general principle is stated by Bloch (you quoted a part of it). And the general principle is to rethrow an exception to the layer where you can handle it.
Whether something is a "checked exception" has nothing to do with whether you catch it or what you do in the catch block. It's a property of exception classes. Anything that is a subclass of Exception except for RuntimeException and its subclasses is a checked exception.
The Java compiler forces you to either catch checked exceptions or declare them in the method signature. It was supposed to improve program safety, but the majority opinion seems to be that it's not worth the design problems it creates.
Why do they let the exception bubble up? Isnt handle error the sooner the better? Why bubble up?
Because that's the entire point of exceptions. Without this possibility, you would not need exceptions. They enable you to handle errors at a level you choose, rather than forcing you to deal with them in low-level methods where they originally occur.
You could define a functional interface to represent actions performed on any Element that might throw a FrameworkException. Then, you just need to implement a method that accepts both the action and the current item. This method both encapsulates the try-catch logic and applies the action to the item.
@FunctionalInterface
public interface ElementAction {
void execute(Element element) throws FrameworkException;
}
public void tryAction(ElementAction action, Element element) {
try {
action.execute(element);
} catch (FrameworkException e) {
// do whatever you usually do for exceptions
}
}
This way you can have your processItems be cleaner like this:
public void processItems(List<Element> items) {
for (Element item : items) {
tryAction(element -> framework.doSomething(item), item);
// . . .
tryAction(element -> framework.doDifferentThing(item), item);
// . . .
}
// cont.
}
edit(just read the comments on the main post):
You can extend the tryAction method by passing in a BiConsumer that takes in an Element and a FrameworkException for custom loggin.
@FunctionalInterface
public interface ExceptionLogger extends BiConsumer<Element, FrameworkException> {}
You would then add it to the tryAction method:
public void tryAction(ElementAction action, Element element, ExceptionLogger logger) {
try {
action.execute(element);
} catch (FrameworkException e) {
logger.accept(element, e);
}
}
Then in your processItems you would add your way of logging the exception:
public void processItems(List<Element> items) {
for (Element item : items) {
tryAction((
element -> framework.doSomething(item),
item,
(element, e) -> System.err.println("this error " + e.getMessage())
);
// . . .
tryAction(
element -> framework.doDifferentThing(item),
item,
(element, e) -> System.err.println("that error " + e.getMessage())
);
// . . .
}
// cont.
}
(this is assuming you are using Java 8+, which you really should be these days)
It sounds like you want the loop to continue whenever a framework exception occurs:
for (Element item : items) {
try {
framework.doSomething(item);
// ...
framework.doDifferentThing(item);
} catch (FrameworkException | SomeOtherFrameworkException e) {
logger.log(Level.INFO, "Corrupted element " + item, e);
}
}
This allows your logic to appear continuous, without being visually broken up by multiple catch blocks.
You should not be seeking to use some magical annotation to hide try/catch blocks from other developers. Spreading out your logic into other places without any reference to them would just make future maintenance dramatically more difficult.
In this case, though, I don’t think there would be any way to do it, regardless. You have to catch an exception if you want to recover from it and continue the loop.