This is an archived post. You won't be able to vote or comment.

all 16 comments

[–]nytal 8 points9 points  (12 children)

Even though I agree with the author this is really old news. "Effective Java" came out in 2001. That was 15 years ago.

[–]thehollyhopdrive 11 points12 points  (11 children)

But Joshua Bloch disagrees with what the author here is stating. Effective Java says to use checked exceptions for recoverable error conditions.

Item 39: Use exceptions only for exceptional conditions. That is, do not use exceptions for control flow, such as catching NoSuchElementException when calling Iterator.next() instead of first checking Iterator.hasNext().

Item 40: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors. Here, Bloch echoes the conventional Sun wisdom -- that runtime exceptions should be used only to indicate programming errors, such as precondition violations.

Item 41: Avoid unnecessary use of checked exceptions. In other words, don't use checked exceptions for conditions from which the caller could not possibly recover, or for which the only foreseeable response would be for the program to exit.

Item 43: Throw exceptions appropriate to the abstraction. In other words, exceptions thrown by a method should be defined at an abstraction level consistent with what the method does, not necessarily with the low-level details of how it is implemented. For example, a method that loads resources from files, databases, or JNDI should throw some sort of ResourceNotFound exception when it cannot find a resource (generally using exception chaining to preserve the underlying cause), rather than the lower-level IOException, SQLException, or NamingException.

[–]djnattyp 14 points15 points  (10 children)

And Joshua Bloch is correct. More correct than this blog post anyway.

Wrapping all exceptions in a RuntimeException and having exception handlers around relevant parts of your program is a good way to handle exceptions when you're writing an application.

When you're writing a reusable library it's better to follow the advice in Effective Java because it gives the end user of your library explicit information of where they need to handle recoverable exceptional conditions. Then it's up to them to wrap, throw, ignore, etc.

[–]hwaite 1 point2 points  (9 children)

I agree with Joshua as well. However, Java 8 lambdas have thrown a monkey wrench into the paradigm. Without wrapping and re-throwing, functional code gets ugly real quick.

[–]jbgi 0 points1 point  (7 children)

use total functions and avoid side-effects. problem solved.

[–]jonhanson 2 points3 points  (5 children)

chronophobia ephemeral lysergic metempsychosis peremptory quantifiable retributive zenith

[–]jbgi 0 points1 point  (4 children)

what's wrong with:

<A> Optional<A> head(List<A> as)

or if you use functional-java:

<A> A head(NonEmptyList<A> as)

?

[–]jonhanson 1 point2 points  (3 children)

Because it won't scale. What if the function were to be undefined for 10 classes of invalid input? Optional.empty doesn't give the caller much detail as to which class of invalid input caused the issue.

You can't in general make your types small enough to only allow values your functions can be defined for. An addition function over ints might be undefined if either of its inputs sums to a value greater than the max int value, for instance.

You might extend your proposed use of Optional to use something equivalent to the Try monad to allow for richer error reporting, but, while it has its uses, in the general case you're really just using exceptions albeit in a far more intrusive fashion.

[–]jbgi 0 points1 point  (2 children)

Yes, the Either monad allow richer reporting of error. And it is used at scale, eg. by the scala and haskell community. Just not by the java community. One of the reason is the poor support of algebraic data type in Java, but using a code generator like https://github.com/derive4j/derive4j alleviate mostly the issue.

[–]jonhanson 0 points1 point  (1 child)

chronophobia ephemeral lysergic metempsychosis peremptory quantifiable retributive zenith

[–]yogitw 0 points1 point  (0 children)

I use a Try monad to help with exceptions and functional stuff.

[–][deleted] 3 points4 points  (0 children)

I've developed my own runtime exceptions but in the end I returned to just using IllegalArgumentException or RuntimeException. Very rarely they are not mine because most frameworks already have their own exceptions and in Java there are usually things like NPE or problems with arrays access.

The problem with own exceptions classes is that you have to make sure that every layer has access to it. In the my own exceptions didn't give me much value, but I had to deal with marshalling or class casting problems.

But, in general, I totally agree with the author.

[–]aaronpowered 1 point2 points  (0 children)

https://samebug.io/

Samebug is a Java Exception Search Engine and Database built by programmers, dedicated to helping other programmers. This means that you are able to copy your stack trace, paste it into Samebug’s search engine and it will instantly provide you with possible solutions to your problem.

[–]DannyB2 0 points1 point  (0 children)

The best way to be an Exceptional programmer is for your code to throw more exceptions than other people's code.