first disclaimer: This is not to cause "language wars". I really need this (the clarification on the subject) for my report, and I just want to have valid and solid arguments.
Ok, so here is the question:
In C++ exception specification has been removed from C++11 standard as it was thought of as causing more hurt than good.
In Java on the other hand exception specification is seen as something good and helpful.
Are those two concepts (the purpose of having exception specification) different in those two languages and that's why they are seen differently by those two communities or those concepts are similar/identical?
Which one is it? Is exception specification a good thing or bad? Or is it good in Java because (and here I'd like to see some reasons) and in C++ is bad because (reasons go here).
Thank you for anyone with constructive help.
Aside from anything else, I think the main difference between Java and C++ exception specifications is that in Java, the specification is part of the function type and the compiler enforces that you can't allow checked exceptions to escape your function unless they're part of the type of your function.
Therefore, Java checked exceptions provided a limited/flawed means of tracking what exceptions are thrown by what functions. C++ exception specifications provide a limited/flawed means of preventing a call to a function from throwing particular exceptions (or any exception).
Since they have different purposes, their success or failure has to be assessed separately for each. To the extent that actual programmers avoid using them, I think you can safely say they've both somewhat failed, but that's about all you could assess the same way for both. That extent is fairly high for Java and very high for C++. The beneficial uses they've had, and hence the exact degree of success in each language, are different.
The exception specification in Java and C++ are working in a very different way.
This is a very good source of information for the C++ point of view. http://www.gotw.ca/publications/mill22.htm
The main drawback of the C++ design was the fact that if you are throwing an unexpected exception it was very likely that your program will crash (see the link for the details). So, the exception specification is a constraint that it will apply too late.
Herb Sutter close the article saying:
Moral #1: Never write an exception specification.
Moral #2: Except possibly an empty one, but if I were you I’d avoid even that.
The Java exception specification framework is different, you have two types of exceptions: checked (compile time) and runtime exception (pretty much like the C++ with no exception specification).
With the checked exceptions, the compiler will force the developer to handle those, otherwise the application will not compile. This is good and useful, however the difference between runtime and checked exception is not completely clear and depends upon the developer and it can generate confusion. Also the checked exception are involving difficult decision even with simple program idioms (for example Checked exception specification and strategy pattern).
The final result, as usual with not clear language features, was a bad use of it. For example, C# designers decided to drop them.
I think, the java design is better than the C++03 for this specific topic (and I am a huge fan of C++), because it allows the developer to write better code in a more descriptive way. However, you need to spend energy (coding standard and code review) to produce consistent code within your development team.
Quite some years ago Java's checked exceptions have fallen out of favor as they, exactly as you put it, cause more harm than help. People nowadays mainly devise ways how to avoid them, usually by wrapping in RuntimeExceptions.
In Effective Java, Josh Bloch still defends the checked exception in the case of "exceptional, but expected, outcome", but the truth is, the API writer is not the one to decide which outcome is expected and which isn't. For example, even a FileNotFoundException can, in context, be an unexpected, fatal outcome.
So, at least, no public library should ever use checked exceptions.
C++ and Java are not even remotely comparable in term of exception specifications, because they differ in term of exceptions:
C++ uses dynamic allocation only when needed, programmers use stack allocation as much as possible (if only to avoid the issue of freeing memory)
Java uses dynamic allocation almost all the time; for objects of user defined types, for arrays (even an array of a size known at compile time)
In C++ many functions can guarantee that no exception will be thrown, ever. I am not talking about exception specification, but about the documented and actual behavior of the function. For the case of a simple function call, it does not matter what the exception specification is, as long as there are no statement that can throw an exception.
[For functions that never throw an exception, exception specifications do matter when the calling code that needs to measure the potential of throwing an exception of a function, in order to call non throwing function in a way that would leave an object in a bad state if there was an exception in the middle. This is done with noexcept in modern C++, in old C++, this could have been done with much more verbose way (also, incompatible between libraries) with a type trait.]
[Note the compiler always had the right to look at the function body that was visible during compilation to determine whether it could throw exceptions, and optimize calling code accordingly (if at least for reducing the size of exception table). Throw specifications only help the compiler when it cannot see that the code couldn't throw.]
In C++ this "never throws" requirement can be documented, and enforced by the compiler, with an empty throw specification (either the good old throw() or the modern nothrow).
Java has no equivalent of that extremely useful guarantee. It can state that some functions do not throw some exception, which is useless for writing exception safe code.
Related
elm's claim of zero-runtime-exceptions is one of its major selling point (see official website),
But if you stop to think about it, nothing stops you from dividing by zero or running out of memory.
What the elm compiler basically does, is forcing you to cover all possible paths that can lead to an exception.
For example:
import String exposing (toInt)
toIntOrZero s = case toInt s of
Err e -> 0
Ok val -> val
But how does this differ from the infamous "checked-exceptions" feature in java ?
public static Integer toIntOrZero(String s) {
try { return Integer.valueOf(s); }
catch (NumberFormatException e) { return 0; }
}
I never heard any claims that java is a zero-runtime-exceptions language.
Please don't get too caught up on what is essentially marketing hyperbole. Of course there are classes of errors that you will never be able to fully rule out with any compiler.
As such, I've always taken these zero-runtime-exceptions claims with a grain of salt, but I think I understand the proponent's intent. Elm was created as an alternative to developing front-end applications in Javascript, which is a messy world where exceptions abound and are just part of everyday life. Elm makes it much harder to shoot yourself in the foot, and without too much effort, if you run through basic sanity testing on your app, you probably won't ever have runtime exceptions in production.
Elm drastically reduces the possibility of exceptions in a few ways.
There is no notion of a throwable exception in the language aside from Debug.crash, which, as its name implies, should really only be used for debugging and stubbing out incomplete logic paths.
Since there are no throwable exceptions, handling problems is most often done through types like Result and Maybe.
This could be thought of as loosely analagous to Java's checked exceptions but conceptually they feel very different than me. Let's face it. Exceptions have been abused. You mention an example in Java, where Integer.valueOf() says that it is going to return an int but if you pass it anything else, it unrolls the stack and bubbles up until some function hopefully catches it. This feels very messy to me, and sure, checked exceptions can aid in reducing the window for failure propagation, but the underlying fact is that an exception is the wrong tool for business logic.
An alternative to throwing an exception would be to have classes analagous to the Result and Maybe Elm types, but that would have been nearly impossible in the early days of Java to do cleanly, and even with Generics, writing such types is more tedious and error prone than the simplicity of Elm's types. And because of Elm's closed type system,
Non-exhaustive pattern matches cause a compilation failure
In Java and Javascript, there is no way to have exhaustive pattern match checking because the type system does not allow it. Sure, Typescript has introduced some functionality but you have to opt into it. In Elm, you have to explicitly handle all cases. Sure, I suppose you could argue that Elm let's you opt out of exhaustive pattern matching by ending all case statements with a catch-all _, but that would just be a silly abuse of the language. Those checks are there to help you, and I feel much safer with the fact that I don't get to opt-in to error checking in Elm - it's there by default!
Immutability
Immutability avoids loads of potential types of errors, too many to get into here.
The Elm Architecture offers a clean separation between Javascript and Elm
Elm compiles down to Javascript, but the Elm Architecture offers a nice clean barrier to keep all the nasty bits of Javascript away from the pure code written by Elm. Any exception that may happen in Javascript should be handled by that barrier, such that I/O errors will always be translated into an Elm-friendly, exceptionless type.
In the end, runtime exceptions are still possible (case in point: the next tagged Elm question dealt with a well-known runtime exception caused by a recursive JSON Decoder definition), and I cringe a little any time I hear someone say it's impossible to get an exception in Elm. The fact of the matter is that exceptions are possible, but nearly every exception you'd run across in day-to-day Javascript development is essentially impossible in Elm.
As a commenter pointed out, Java has unchecked exceptions, so runtime errors do occur. Elm also has unchecked exceptions, for things like division by zero, but gets rid of the ones most commonly seen in practice. And as Chad's answer mentions, Elm's Maybe/Result types work quite differently in practice than Java's checked exceptions. An experienced Elm programmer would not write a function like toIntOrZero (and if they did, they would probably not use case ... of, preferring instead something like toIntOrZero = String.toInt >> Result.withDefault 0).
Chaining multiple operations together with Result.map, Result.andThen, and so on gives a very expressive way of handling error cases without forcing the programmer to get too deep in the weeds. For example, if we want to write a function that validates an ID by converting it to an Int, looking it up in some data structure (when it might not be there), and then verifying some property associated with that user, we can write something like this:
lookupUser : Int -> Result String User
lookupUser intId = ...
userInGoodStanding : User -> Bool
userInGoodStanding user = ...
isValidId : String -> Bool
isValidId id =
String.toInt id
|> Result.andThen lookupUser
|> Result.map userInGoodStanding
|> Result.withDefault False
This reads, "convert the ID to an int, then look up the associated user, then verify the user, and if anything failed, return False." Your mileage may vary, but once you get to used to it, I (and many Elm programmers, I think!) find this to be a really nice way of writing code robust to errors.
Could it be said that RuntimeException's may play a role in defining an operation, as part of the notion of a classes ADT and a particular operations "contract".
Since one chooses to include chosen runtime exceptions in the 'throws' list in a methods header (as well as a methods javadoc) - it is not forced by the compiler and is discretionary depending upon the exception - could this not be considered an effort to emphasize something about the intention of a methods "contract" and how it should be understood to work? Is this the case?
We recognize that some RuntimeExceptions's are simply thrown as "errors" for program logic that needs correcting during development and testing, whereas others could be considered to perform a similar role to that of checked exceptions. Here by embodying instances where a handleable and recoverable situation may occur - a client user should be able to take some reasonable action to allow the sw system to recover and respond appropriately. One designs an ADT and an operation to emphasize how it should be used. I wondered (considering the above) if we should consider as part of this:
"The conveying to the client developer of the need to handle certain Runtime Exception's that can sensibly be handled and anticipated"?
Do we consider the declaration of RuntimeException's in an operations header and documentation to be signalling such an intention and expectation by the code/ API developer to the client user?
Emphasizing the RuntimeExceptions it may throw by declaring them in a throws section (that one should thus handle) and or, declaring them in a javadoc (that one should instead potentially just be aware of) could perhaps be considered as part of this “contract” - that one should understand and uphold in defining and working with an interface (an operation). Therefore, by choosing to emphasize certain RuntimeExceptions (which are a choice), could this therefore be a part of the concept of "design by contract" that one shapes and expresses – it is about intention (what a method should provide as a service, but (pertinant here) - how the method is intended to be used by a client and his/ her expected responsibilities)?
Also, if/ or what, is the relationship between the throwing and documenting of Runtime Exceptions and the software design principle of design by contract is?
Another way of looking at my question i suppose is - One can catch a runtime exception if desired. I think the vast majority of cases where a runtime exception might occur and is thrown relate to situations that never or should never occur in correct client code. Most of these situations relate to incorrect logic or misuse of a method (and handling code would be excessively numerous and not sensible to include in these situations). However, in some less frequent cases, it is possible for some runtime exceptions to be situations that one could (and should) handle. This is why I think (I interpret I coud be wrong), the compiler doesn't require one to handle runtime exceptions - the compiler cannot tell the difference. It cannot distinguish. Checked exceptions are almost always sensibly handleable, but most runtime exceptions are likely not. The nature of a runtime error governs this. – Another angle on my question I suppose relates to the notion that the latter can sometimes be the case and are we supposed to consider this as part of the contract we emphasize as described above and the software design principle of "design by contract"?
Since neither the throws clause is required by the Compiler for subclasses of RuntimeException if you throw one in a method, nor is it required to catch them if you call such a method, it is just for documentation.
When we create a CustomException by extending Exception class it is checked by compiler, but even though RuntimeExceptions extend Exception class are they not checked by the compiler.
How is this established in the compiler. I found a section in JLS stating why.
Why Runtime Exceptions are Not Checked
The runtime exception classes (RuntimeException and its subclasses) are exempted from compile-time checking because, in the judgment of the designers of the Java programming language, having to declare such exceptions would not aid significantly in establishing the correctness of programs. Many of the operations and constructs of the Java programming language can result in runtime exceptions. The information available to a compiler, and the level of analysis the compiler performs, are usually not sufficient to establish that such run-time exceptions cannot occur, even though this may be obvious to the programmer. Requiring such exception classes to be declared would simply be an irritation to programmers.
Is there something happens behind the scenes like in the case of marker interfaces.
I am looking for some source that can explain how it is done and also why there is no parent class for all checked exceptions?
Is there something happens behind the scenes like in the case of marker interfaces.
The fact that RuntimeException is exempted from the rule that all subclasses of Exception are checked exceptions is simply part of the spec.
How this exception to the rule is implemented is compiler dependent.
The compiler checks all Throwable sub-classes except sub-classes of Error and RuntimeException. It just checks whether the Throwable is a sub-class of these classes.
Note: you can have a sub-class of Throwable which is not an Error or an Exception and it will be checked.
At any point in time, someone can enter zero into your program. If you ever divide, that could result in a divide by zero error, which will throw a RuntimeExcpetion called ArithmeticException.
Now if you needed to include try / catch blocks around all of your division statements, the code would be cluttered with error handling that detracted from the readability of the main purpose of the code, which might be anything (but probably isn't about catching divide by zero errors).
Java either had the choice to strike a balance between readability and robustness, or to allow robustness in all cases with some "assumptions" that enhanced readability. In other words, when the Java language was being laid out, a decision to balance readability with robustness would look like a decision between polluting user written source code with a need to capture ArithmeticExcpetions around any division operation. The alternative, which is to always ensure robustness, but make certain kinds of Exceptions not subject to required capture, ensures program robustness without an impact on source code readability (at the cost of knowing that the language is slightly more complex because it has two categories of Exceptions).
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).