Is there any way to get a class that explicitly throws the (non-runtime) exceptions and only the (non-runtime) exceptions that the body throws?
I know how to do this with a fixed number of exceptions, like:
public interface Throw1Callable<T, E extends Exception> {
public T call() throws E;
}
This way, when call is invoked, you don't have to handle Exception and instead only have to handle RuntimeExceptions and E. But this doesn't scale at all. If I wanted to do this for two exception, I'd need to make a new class for Throw2Callable etc. And Java (and probably all languages) doesn't offer variable number of generics or anything of the sort that might help.
Is there a good way of encapsulating the above?
edit for clarification: Let's say A.a throws IOException. I'd like to be able to do ((Throw1Callable)() -> A.a()).call() and catch only IOException instead of catching Exception. ((Callable)() -> A.a()).call() will throw Exception instead of just IOException.
This boils down to some kind of "vararg" type parameter which is not possible in Java.
So probably ThrowXCallable is the best you can do here. I don't think "scalability" is a big problem here, you will probably not need more than Throw5Callable.
Java itself takes this approach - see BiFunction.
Related
The below picture shows that "Checked" and "Unchecked" Exceptions are subclasses of Exception. I find it confusing that you need to catch an Exception but you don't need to catch a RuntimeException, which directly inherits from Exception. Is there a reason that the devs didn't let us throw Exceptions without needing to catch them?
More specifically: Why can you ignore only RuntimeExceptions and it's children? Why wasn't there a Class introduced called CheckedException extends Exception and you only need to catch it and it's children?
The confusing part is, that you can throw everything below RuntimeException without issue, but when you move up to Exception in the hierarchy, you need to catch it at some point. This is confusing because "abstraction" normally works otherwise. The more you move up, the simpler and more meta everything gets. This is not the case here. The more you move up, the more you have to do (like, putting try/catch after reaching Exception).
If Exception was unchecked then you could implicitly cast checked exceptions to unchecked ones, which would mean that you could throw checked exceptions without catching them like:
public void f() {
Exception e = new IOException();
throw e;
}
and also with overriding methods, if you throw a more specific exception, you can add the requirement to catch the exception that wasn't in the superclass:
public void f() throws Exception {
}
...
#Override
public void f() throws IOException {
}
Suppose they designed it the other way. We have a CheckedException class, and subclasses of that need to be handled, but not other subclasses of Exception.
Now we call a method that might throw an arbitrary Exception:
public static void example() {
functionThatThrowsException();
}
Do we need to handle it? Yes, because that Exception might be a CheckedException. If we didn't need to handle it, we'd be bypassing the checked nature of checked exceptions.
A throwable type with checked descendants must be treated as checked, so checkedness naturally propagates up the inheritance hierarchy. Contrapositively, an unchecked throwable type cannot have checked descendants, so uncheckedness naturally propagates down. This makes it natural to make checkedness the default, and single out specific classes and their descendants as unchecked.
CheckedException (Which does exist) and RuntimeException both extend Exception. Because of this, if something throws a generic Exception (which is always a bad idea), there is no way to tell if the exception could be one or the other, so you have to catch it in case it's a checked one. If you think of the hierarchy in this way, it actually does get simpler the farther up you go.
You seem to have the idea that checked exceptions are more "complex" because you have to do more to work around them. This isn't too healthy a way of thinking about it. Instead, consider this: Exceptions are problems with the program itself - the code. We need to find these exceptions and handle them properly. After already having this concept of exception handling, we discover that there are some problems that we simply can't predict.
"How was I supposed to know the user would enter 'meow' when asked for an integer! I shouldn't have to code around that!" And so, NumberFormatException was born, and you don't have to catch it because it's a "logical error", not an issue caused by bad code (Although, arguably, it might be considered bad code if you don't handle this situation in some way).
In short, reverse your thinking. Exceptions are problems with the program that can be handled. There are some exceptions, however, that are unexpected and are a result of bad design more than incorrect code. Thus there is the addition of RuntimeExceptions which cannot possibly be expected to occur, but certainly can occur.
Perhaps it would help to not think of exception classes in terms of inheritance but simply disjoint sets of classes, one set is checked and other is not. You're right that there could be a CheckedException class allowing us to check only when explicitly intended.
However having the broader/generalized range checked helps in enforcing the catch or specify pattern. Having checked exception allows a reader of the code to figure out quickly that this piece of code needs special attention and enforcing their handling at compile time reducing the runtime bugs.
We can throw any kind of exception, checked or unchecked. If Exception or any super class of RuntimeException were to be set as checked exception then all the sub classes would become checked exceptions. As compiler is most likely checking if an instance of exception or a class in the throws clause derives from a class. It could easily have done that by checking for a specific package which probably would have been more appropriate as being checked or unchecked has simply nothing to do with the inheritance.
Why throws, on a method, is part of its signature? It seems strange to include it. Here is an example where it is in the way:
#Overide
public void foo() {
throw new UnsupportedOperationException();
}
If anyone were to see this method from the outside, they might try to use it without knowing that it is not supported. They would only learn it on trying to run the code.
However, if they could do something like this they would know by looking at the method that it is not supported and if UnsupportedOperationException was not extending RuntimeException, they would get a compilation error. EDIT1: But this is not possible because throws is part of the signature so override will not work.
#Overide
public void foo() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
This question concerns Java's design, so I know that it might be hard to answer without one of the people that work on it drops by and answers it, but I was hoping that maybe this question has been asked to them before or that there might be an obvious reason to have it this way to explain why.
The throws part does not indicate that the method is required to throw the mentioned exception(s), not even at particular occasions. It only tells that the function is allowed to do so.
Including throws UnsupportedOperationException will consequently not mean that the method is unsupported. Besides the UnsupportedOperationException is a RuntimeException so a method may throw that anyway.
Now for the reason one would require it in the signature of the method, it boils down to the ability to have checked exceptions at all. For the compiler to be able to decide if a method can only throw the specified exceptions it must be able to decide that the methods that it calls can't throw uncaught exceptions.
This means for example that overriding a method means that you can't add exceptions that might be thrown, otherwise you would break the possibility to verify that a method that calls that method can't throw anything else than it has specified. The other way around would be possible (but I'm not sure if Java supports that), overriding a method that may throw with one that may not throw.
So for example:
class B {
int fubar(int) throws ExceptionA {
}
int frob(int) throws ExceptionA {
return fubar(int);
}
}
class D extends B {
int fubar(int) throws ExceptionB {
}
}
Now frob is specified to possibly throw only ExceptionA, but in calling this.fubar it would open the possibility that something else is thrown, but fubar is defined to possibly only throw ExceptionA. That's why the D.fubar is an invalid override since that would open up the possibility that this.fubar actually throws ExceptionB and the compiler wouldn't be able to guarantee that frob doesn't throw ExceptionB.
Java has two different types of exceptions: checked Exceptions and
unchecked Exceptions.
Unchecked exceptions are subclasses of RuntimeException and you don't have to add a throws declaration. All other exceptions have to be handled in the method body, either with a try/catch statement or with a throws declaration.
Example for unchecked exceptions: IllegalArgumentException that is used sometimes to notify, that a method has been called with illegal arguments. No throws needed.
Example for checked exceptions: IOException that some methods from the java.io package might throw. Either use a try/catch or add throws IOException to the method declaration and delegate exception handling to the method caller.
One thing which no one has mentioned is a very important answer to your question:
Why throws, on a method, is part of its signature?
that throws, is NOT part of the method signature.
JLS 8.4.2. Method Signature makes it quite clear, that:
Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (ยง8.4.4), and, after adapting the formal parameter types of N to the type parameters of M, the same formal parameter types.
If anyone were to see this method from the outside, they might try to use it without knowing that it is not supported.
That's exactly the main reason, why throws is designed in a way to be checked at compile-time for all Checked Exceptions - clients of the method will be aware what this method may possibly throw.
Checked Exceptions are enforced to be either handled or specified to be thrown (but this specification is NOT part of the method signature).
Unchecked Exceptions do not have to be either handled or specified to be thrown, and Oracle's tutorial are good at explaining - why:
Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.
When I throw checked exceptions from a method should I just declare the super class of the exceptions in the method signature or all the different types? If I have the following exceptions:
private class SuperException extends Exception {
}
private class SubExceptionOne extends SuperException {
}
private class SubExceptionTwo extends SuperException {
}
Should the method signature be:
void confirmAccount() throws SubExceptionOne, SubExceptionTwo;
or
void confirmAccount() throws SuperException;
In the last method signature, how do I tell other developers what exceptions that could be thrown from the method? If the different sub types need different handling?
The interface should be as stable as possible. So probably Super. Many libraries use the "Super" strategy, because exception specs cause far more annoyance in maintainability than readability or safety they add. Even the IOException is a Super that nearly all Java library code uses instead of declaring more specific exceptions. (But when they do declare more specific exceptions, it's because the contract is that more general IOExceptions won't be thrown. Read on.)
You might list Sub1 and Sub2 if you really do want to say each of those exceptions can be thrown, but don't want to say that any derivative of Super can be thrown. Perhaps Sub1 is NumberCrunchException and your method calls crunchNumbers() and users of your method can be assured that's the only exception-ful thing your method does. In that case the specific strategy is better.
If the different sub types need different handling, then definitely declare the two different exceptions. Never expect the developer using your method to guess that you are actually throwing different types of exceptions.
If you declare two distinct exceptions, and the user knows from the Javadoc that they are actually descendents of the same class, the user may choose to catch them both with a catch (SuperException e) rather than two individual catch clauses. But it depends on the user's choice.
If you don't declare them separately, your IDE is not going to add the appropriate #Throws to your Javadoc comment. And your Javadoc will therefore only indicate that you're throwing SuperException, which will leave the user in the dark. Solving this by just putting it in the text of the comment is not a real solution. If any tool is using reflection to determine what your method throws, it will not see the individual exceptions in the array returned from Method.getExceptionTypes().
If the functionality expected of the different exceptions is more or less the same and it's just a matter of how they will appear in the logs, it may be better to just use the parent exception, with different messages.
The throws clause is there to convey useful information to the calling method about what might go wrong during invocation of this method. That means that how specific you are will depend on how much information you want to convey; and that will be application-dependent.
For instance, declaring throws Exception is almost always a bad idea: the information this conveys is just "something might go wrong", which is too vague to be useful. But whether calling classes are going to need perfectly fine-grained information in the throws clause is something you need to decide by looking at your program. There's no set answer.
In my Java project, I have the following class / interface hierarchy:
public interface ProductSearcher {
Set<Product> search(String request);
}
public interface OnlineProductSearcher extends ProductSearcher {
}
public interface DatabaseProductSearcher extends ProductSearcher {
}
The OnlineProductSearcher searches for products at some remote machine (e.g. an implementation uses HTTP), while the DatabaseProductSearcher searches for products within my local machine (e.g. an implementation uses JPA).
As it turns out, from time to time, the OnlineProductSearcher may have problems searching for products because the remote machine is down, is rate-limiting my requests, responses with 5xx, 4xx, and whatnot.
So I had the idea to have my OnlineProductSearcher implementations throw an RemoteMadeProblemsException whenever there is a problem related to the remote machine.
And as I want to force any OnlineProductSearcher user to handle these exception gracefully and not forget to do so, I made RemoteMadeProblemsException a checked exception, i.e. RemoteMadeProblemsException extends Exception.
So I went along and had the idea to redefine OnlineProductSearcher like this:
public interface OnlineProductSearcher extends ProductSearcher {
Set<Product> search(String request) throws RemoteMadeProblemsException;
}
But in Java, it is not possible to redeclare/constrain methods from a supertype inside a subtype (Eclipse tells me "Exception RemoteMadeProblemsException is not compatible with throws clause in
ProductSearcher.search(String)")
Now I see two solutions to this situations:
define ProductSearcher.search(String) to throw a RemoteMadeProblemsException.
or make RemoteMadeProblemsException extend RuntimeException and don't have OnlineProductSearcher.search(String) declare a throws clause.
I find both solutions inadequate:
the first solution e.g. forces any user of DatabaseProductSearcher.search to catch/throw a RemoteMadeProblemsException which doesn't make sense (it's a local database after all).
the second solution opens the door for sloppy programming. E.g. someone uses OnlineProductSearcher.search(String) and forgets to try-catch a RemoteMadeProblemsException, letting the exception fall through and ripple up.
What are better solutions to this "only some subtype may throw an exception" problem?
The problem you have is this:
ProductSearcher x = new OnlineProductSearcher();
This is entirely legal syntax and now if someone calls x.method() there is no way for Java to know about that checked exception.
This is why subclasses can only make implementations more specific. They can return subclasses and accept super classes but not the other way around. This is because the requirement is that any call made to the super method is also valid against the subclass method.
For example if:
Number process(Integer i) {
}
is a super class then a valid subclass is:
Integer process(Number i) {
}
Because every call to process in the super class is also valid in the sub class. The exact same argument applies to throws declarations. By making the sub class throw a checked exception you make it impossible to treat it as a method with the same signature as in the super class.
The solution to your dilemma is to define a more generic exception ProductSearcherException and have ProductSearcher throw that exception.
Your OnlineSearcherException then subclasses ProductSearcherException and your throw declaration becomes legal.
One thing you can do to improve things involves having three classes instead of one:
Your base ProductSearcher which declares the method as throwing the exception
Your local implementation which does not throw the exception
The remote implementation which does throw the exception (or a more specialized one).
This does weaken the ability for people to doProductSearcher x = new LocalProductSearcher and then use the more generic class (as then they would need to catch the exception) but for anyone using LocalProductSearcher throughout they would never need to do the catch.
Note though that even in the local case you may find yourself needing to throw exceptions in the future so having them is not terrible.
IMHO You should add the throws Exception to your superinterface (and probably some more refined version, not just Exception).
The reasoning is that if you do not declare throws exception, then your contract is: Under normal execution no implementation of this method should throw an exception. In your program this is clearly not the case, as the remote may experience problems.
Your reason for not adding an exception to the database version is silly: The DB is local today, but may be remote tomorrow. And local DBs can have problems too.
If you REALLY don't want to catch exceptions from the DatabaseProductSearcher version, then you need to reference it as itself, not as the superinterface, and redefine the method in DatabaseProductSearcher to not throw anything. Then when you refer to it by that interface, you are not forced to catch anything, as the compiler now knows that this version is safe.
Java Runtime Exception is used to check un-checked exception. It is accepted standard that to sub class JavaRunTimeException. Can you please explain me the reason behind sub classing without directly using it as below.
try {
int x = Integer.parseInt(args[0])/Integer.parseInt(args[0]);
} catch (RuntimeException e) {
}
Recommended approach
public class ServiceFaultException extends RuntimeException {}
try {
int x = Integer.parseInt(args[0])/Integer.parseInt(args[0]);
} catch (ServiceFaultException e) {
}
I would like to know reasons for this recommendation. ?
Exceptions are used to give some meaning to an error that is not handled right away where it occurs.
Subclassing RuntimeException allows you to give more meaning and differentiate between several RuntimeExceptions.
For instance, it is useful to be able to tell the difference between IllegalArgumentException and NumberFormatException, which are both RuntimeExceptions.
EDIT: As #Dyrborg said, catching RuntimeException can also be dangerous because anything could throw it without your knowledge. Better handle only what you control.
ASIDE:
You could tell me "why not a checked Exception then ?".
I usually use RuntimeExceptions when it corresponds to an incorrect use of a method (illegal argument for instance). It means something the programmer can ensure to avoid. When it comes to user input, or internet connection, which is not reliable, then Exceptions are more appropriate, because the programmer must handle these error cases.
Can you please explain me the reason behind sub classing without directly using it as below.
The same reason as applies to subclassing any other exception. The language provides the facility to catch specific subclasses, so why wouldn't you use it?