What's the difference between a wrapper exception and the multi-catch statement they have. Aren't they the same and I can use the multi-catch instead of build up my own exception and in it wrapper?
I think you are confusing 2 concepts. The multi-catch is a convenient way of saying here is the code for handling these conditions. It just provides a more terse version of older code. Whereas wrapping an exception allows for you to provide your callers with a more meaningful exception - this is a question of how you design your application. For example, I have worked on applications in the past that chose to wrap all data access exceptions in a DAOException. The caller knows generally something went wrong and can act accordingly. They can also look inside to see the specifics if needed.
Good pracice is to avoid creation of custom exceptions when you have standard one that serves exactly the same purpose. But more important thing is that wrapping method calls with your one code can make you code less readable. Moreover, trowning new exceptions is a resource-consuming operation!
Also, some block of code can throw exceptions that are very different by nature. It is not very wise idea to theat them as something similar, even if the exception handling is similar in your case.
Related
The following method will warn about IOException if called in Java code but will simply ignore any warning in Kotlin because IOException is a checked exception.
ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE)
Java forces developers to take safe action in case it throws an exception but in Kotlin it just overlooks the exception creating a potential bug source. I'm quite sure there are lots of similar cases where checked exception is simply ignored.
The question is how to handle such cases?
Java will not warn you if method is throwing unchecked exception, how are you handling this case? The best you can do here is to check java doc or the source of the calling method to see if it throws any exceptions. Or just to catch any exception somewhere in your code which calls this method.
If you are asking why Kotlin doesn't have checked exceptions unlike java, the official Kotlin docs about exceptions provides an explanation why they decided to move away from checked exceptions. Quote:
Examination of small programs leads to the conclusion that requiring exception specifications could both enhance developer productivity and enhance code quality, but experience with large software projects suggests a different result – decreased productivity and little or no increase in code quality.
UPD: Article by kotlin lang architect about this matter: https://elizarov.medium.com/kotlin-and-exceptions-8062f589d07
Kotlin doesn't prevent you from catching any or all exceptions; it just doesn't force you to do so, like Java does.
So you can still do e.g.:
try {
ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_WRITE)
} catch (x: IOException) {
// …
}
As for how you know that the method could throw an IOException… that's tricky. If it's a Java method, then of course its JavaDoc will specify it (and you can see that from your IDE). But if it's Kotlin, well, the documentation might say; or if you have the source code, you could check that. But I'm afraid there's no real way to know! All you can do is guess — and ensure that you catch all exceptions at critical points.
Treating all exceptions as unchecked is not without controversy; see this long-running discussion.
There are clearly a few situations where Java-style checked exceptions would be impractical: for example, when calling lambdas or function references. (Java itself forces you to handle or wrap checked exceptions in such cases, which can be unwieldy.) For big programs which cover multiple layers of abstraction, there's the problem of exceptions bubbling up to a point where they make little sense; the usual solution there is exception translation: catching them and rethrowing more appropriate ones. And there's also the problem that too many bad developers simply catch all exceptions and ignore them (or, at best, log them) without considering how or where they should be handled.
But you might well think that dropping all exception checking is throwing the baby out with the bathwater…
(I've suggested that Kotlin should do exception inference — working out which uncaught exceptions a method could throw, and assuming a #Throws declaration for them — which would solve most of the problems around knowing which exceptions could be thrown at any point, without requiring them to be caught or invalidating any existing code. But I'm probably failing to see some problems around that, because while it seems an obviously good idea to me, it hasn't been well received…)
I want to know whether it would be right to use exception classes as regular classes to handle application errors (just regular controlled errors, not exceptional ones), without throwing them with the proper language clause (eg. instantiating them and returning them from a method). I've been discussing this topic recently with some colleges and I think that exceptions should only be used as exceptions, but I'd like to listen to more opinions.
What you mean by "controlled error" is actually known by the name checked exception.
"Exceptional exceptions" are known as unchecked exceptions.
The difference is explained here: Checked vs Unchecked exception
So, you see: Java comes with a built-in mechanism to distinguish between
exceptions caused by programming mistakes (e.g. NullPointerException when passing unexpected null as an argument) -- unchecked exceptions
versus anticipated exceptions that should be handled by the caller (e.g. IOException when some kind of I/O went wrong) -- checked exceptions
Returning instances of Exception (or any subclass) would be considered a misuse in virtually all circumstances.
You could ask your colleague how he/she would implement an exceptional outcome of a method with this signature:
public String createStringOrFailWithException();
Returning an Exception? Certainly not, because this requires a different return type.
Throwing the exception instead allows you to keep the return type, and to benefit from vast exception handling capabilities, including finally blocks and try-with-resources statements, to give only two examples that you don't want (should not) implement by yourself.
I suggest keeping Exceptions "exceptional". I.e. don't build them into your app logic. Use more meaningful things like a ActionXResponse class etc that could indicate failure, and even have an Exception as a property which the controller could check for "controlled exceptions". It's much more meaningful when you have your own class as a response.
Another guideline I'd suggest, along with keeping Exceptions "exceptional" is to avoid checked Exceptions (compile-time).
Three ways I see here:
1) make function return that value explicitly
2) add additional argument to the function's argument list and pass string holder as that parameter. After the function completes its execution, that string holder will contain the result of the function.
3) throw an exception from that function that will contain the result.
I for myself see first choice more preferable because it's simple, intuitive and straight.
On the other hand, when execution of the function goes in a wrong way there may be additional choices like throw an exception or use a variable passed through parameter to save errors if any happen.
Intuitively, I see that ideal choice is to have explicit return value and throws declaration. So return value is used for normal execution and caught exception will signal about abnormal situation. But I myself don't like exceptions too much if only it is not the completely unpredictable error, so I'd use explicit return value and additional parameter to hold some extra-situation logs or errors.
Please advise books or articles on the subject (it shouldn't necessary talk about Java, any other languages with similar mechanisms are also suitable).
You absolutely want option #1. Exceptions are not unpredictable; if you use them correctly, they are in fact entirely predictable. You can throw different exception types based on the error (FileNotFoundException, IllegalArgumentException, SomeConditionSpecificToMyAppException, etc), and those exceptions can contain any error or diagnostic information you need to convey.
Here's a good section in the Java SE tutorial on exceptions: http://docs.oracle.com/javase/tutorial/essential/exceptions/
Java methods have return values for a reason: to return their results. In the vast majority of cases #1 should be your only choice. Even if you want to return a wrapper object e.g. because you need to return multiple values, you should probably just return the thing...
Exceptions are just that: they are thrown in exceptional (i.e. abnormal) circumstances. Since traditionally throwing an exception also implies a performance impact, exceptions should not be thrown during normal operation.
Why are you trying to confuse yourself?
EDIT:
On the other hand, exceptions are quite suitable for rare/abnormal conditions:
They have built-in support for the generation of debugging information. Getting a stack trace is half the battle in dealing with most bugs.
All decent debuggers allow for thrown exceptions to be used as a break point, which can be invaluable.
Exceptions allow for error conditions to be passed up the method call chain relatively transparently, allowing for the error handling code to be placed with as much granularity as desired.
Exceptions are the standard way to deal with error conditions in Java. This should be enough for most programmers. Please respect the people that will have to work with your code and don't break such basic conventions by reinventing the wheel...
I would use choice 1 almost every time. There is nothing stopping you throwing a Exception as required.
Please read Code Complete by Steve McConnell. It's all there.
We all know it is needed.
But WHY is it needed in Java alone, when other similar languages that have exception handling capablities don't require us to write "throws Exception"? Is there anyone who knows what was happening when Java language was designed and why they made it that way? Just curious.
P.S. This may not be a practical or really necessary question - it might not help me in anyway with my ongoing projects. But certain language features kindle my curiosity :D
Edit
Looks like my question was very vague! I think I worded the question wrongly. We need to use the "throws Exception" kind of syntax at some points during programming when dealing with Java code. But something like that is never needed in C# or C++ or even VB.Net and PHP. So why Java alone insists on this?
As other answers here have pointed out, the throws clause is only required for checked exceptions, which is a feature that currently only exists in Java.
The official answer as to why Java has checked exceptions is well documented:
Why did the designers decide to force
a method to specify all uncaught
checked exceptions that can be thrown
within its scope? Any Exception that
can be thrown by a method is part of
the method's public programming
interface. Those who call a method
must know about the exceptions that a
method can throw so that they can
decide what to do about them. These
exceptions are as much a part of that
method's programming interface as its
parameters and return value.
However, this decision is highly controversial, even within the Java community:
Recently, several well-regarded
experts, including Bruce Eckel and Rod
Johnson, have publicly stated that
while they initially agreed completely
with the orthodox position on checked
exceptions, they've concluded that
exclusive use of checked exceptions is
not as good an idea as it appeared at
first, and that checked exceptions
have become a significant source of
problems for many large projects.
Eckel takes a more extreme view,
suggesting that all exceptions should
be unchecked; Johnson's view is more
conservative, but still suggests that
the orthodox preference for checked
exceptions is excessive. (It's worth
noting that the architects of C#, who
almost certainly had plenty of
experience using Java technology,
chose to omit checked exceptions from
the language design, making all
exceptions unchecked exceptions. They
did, however, leave room for an
implementation of checked exceptions
at a later time.)
Personally, I find checked exceptions to be useful only when your API makes a habit of catching all exceptions and re-throwing them as something appropriate to your abstraction layer. For example, an in-memory object cache that happens to use a disk or SQL backend to cache data should never throw IOException or SQLException -- instead, it should throw (and declare) some user-defined exception like CacheFailureException or similar.
Also, you might find Ned Batchelder's article Exceptions in the Rainforest illuminating in regard to this question.
It declares that the method can raise an exception, and allows developers and their tools to ensure that they have considered that possibility.
However, the question is imprecise. The declaration is only required when the exception is a "checked" exception. And then, a more specific type of exception should be declared. Throwing a java.lang.Exception is poor style.
Runtime exceptions, that is, exceptions raised by the runtime when specific bugs are encountered, are not required to be declared. Runtime exceptions should be thrown when the error can be prevented by better programming, and doesn't depend on environmental conditions at runtime.
There are two types of exceptions
Checked Exceptions
UnChecked Exceptions
The throws clause tells which checked Exceptions are thrown by the method so that the caller can handle these in the code or they would have to add the throws clause so that in the end someone will have to handle these exceptions.
Java does not require you to write throws Exception on a function declaration, so it is not "needed" in general. It requires you to declare the exceptions that may be thrown by the function, which might be no exceptions at all, or just runtime exceptions. Indeed, using throws Exception is probably a sign of lazy coding, as it acts as an uninformative catch-all.
edit — well now that you've edited your question, the answer you're looking for (as others have said) is that Java has the concept of "checked" exceptions. It was simply a design decision, to supposedly improve code quality. It probably doesn't really help much in the long run; you can't fix a bad coder with a language trick.
Java is a very organized language which prevents in many situations the unexperient user from missing something relevant or of importance, at least so that errors can be displayed later with a good hint or explanation for what is missing. Forcing you to mention the exceptions on a function/method declaration is a way to keep with that politics and at the same time a way to allow you to define your own specific exceptions and putting them to use.
The point of declaring exceptions in Java was to force the programmer to handle the errors that can arise when executing the program. However, experience showed that in a lot of cases, programmers' "handling" of exceptions did not really handle the exceptions but instead ignored them:
void writeToFile() {
try {
...
} catch (IOException ex) {
// Nothing here
}
}
So in languages more recent than Java the designers preferred not to check exceptions, so that programs without error checking would at least crash with a meaningful stack trace, so you would have a bug easy to debug instead of your program "misteriously" malfunctioning.
Personally I like checked exceptions in Java because:
I do not mishandle exceptions.
Exceptions make me be aware of possible problems that my code could have.
Code is better documented that way.
but I can understand unchecked exceptions. Most of the time I handle an exception is to log it, wrap it with some subclass of RuntimeException and rethrow, because they could only be caused by bugs / misconfiguration / broken deployment. I like to use checked exceptions only for business rule violations.
As I have understood the rationale as put forward by the Java designers, the error situations are generally put in two categories:
Those that are non-fatal and the calling code with good reason should be able to recover from. FileNotFoundException when reading form files, and IOExceptions when working with sockets.
Those that are fatal if they cannot with good reason be expected by the calling code. This includes ArrayIndexOutOfBoundsException and ArithmeticException (when dividing by zero).
Is there any point in having a com.myco.myproj.MyProjRuntimeException,
which completley extends RuntimeException?
Yes. Do throw unchecked exceptions, and subclass them.
There is much talk about whether checked exceptions are really any good. In a nutshell, if I throw a checked exception, does my client really have anything to do with it?
Unchecked exceptions are a good way to notify your clients about exceptional situations (including illegal pre-conditions), and yet not burdening them with the need to wrap calls to your API with try-catch blocks, which most of the time basically serve no purpose, other than debugging, tracing, etc.
So why not throw a RuntimeException? It's not elegant, and it's less readable. Make it your own exception which derives from it, even if it's for no reason other than being more specific when throwing the exception.
It depends on if you want to handle the exceptional condition differently than other exceptions farther up the call stack. If you intend to catch and handle the exception, then I'd recommend creating the custom type. It makes for more legible code and cleaner catch clauses. If you're not going to catch the exception, then there's probably little reason to create a new type.
Not really. The extra information you get from having the exception name show up in a stack trace could be given by simply setting the message string of a standard RuntimeException. However (come to think of it), it might be useful to subclass RuntimeException simply to prepend a custom string onto any message.
I tend to only make custom checked exceptions; generally, the standard unchecked exceptions cover enough potential cases already.
Many people (me and the designers of C# included) believe that checked exceptions are a failed language experiment and avoid them. Then, creating your own exception hierarchy under RuntimeException is an obvious step.
in Effective Java, Joshua Bloch writes:
Use run-time exceptions to indicate
programming errors. The great majority
of run-time exceptions indicate
precondition violations.
That being said, you could use that run-time exception as a base class for a hierarchy of run-time exceptions, used in your project. That way, errors become more legible and traceable.
In my opinion, you should only create new Exceptions if you really need them, i.e. want to catch them and do a specific treatment on them. On all other cases, I don't really see the usefulness.
It's a good style to maintain your own exceptions hierarchy.
But I've seen just a few people who can use this technique with real profit.
Subclass exceptions based on how they are handled rather than who wrote them...
Normally runtime exception can't be handled in another way than logging the error and possibly display an error message.
Checked exceptions might possibly have a specific fallback, and in that case they should probly not subclass a "MyFrameWorkException" - as in that case, catching a MyFrameWorkException would not do more than the generic catch (logging etc.)
It is a rather bad practice to invent a whole hiearachy of exceptions that does have little in common except the fact that they belong to a particular framework.
(packages are supposedly used for just that.)
It is perfectly ok to subclass RuntimeException (if the existing subclasses are not a god fit)
Document unchecked exceptions. Be conservative with checked exceptions, and don't build hierarchies.
Rod Jonhson wrote on this in Expert one-on-one J2EE design and development and as in Tom's answer RuntimeException should be used for programming errors.
A good example is SQLException, lower level data access API should catch them and throw your own "SQLRuntimeException" as most of the time the calling code cannot do anything with the exception. This way, your higher level apis are not forced to catch or carry lower level exceptions in their signature, which make code simpler and more focused on the business domain.