Monday, June 16, 2008

Common Java unchecked exception types

I've noticed a lot of confusion about what type of unchecked exception is the right one to throw under various circumstances. Here's a very simple explanation of the most common types.

NullPointerException - multiple schools of thought on this one. Of course, it's thrown automatically by the runtime when you try to dereference null. Many say that you should never rely on this behavior, and should always check for null explicitly. Many also believe that when you find a null reference, you should throw IllegalArgumentException instead of NPE. This way, a thrown NPE always indicates some programming error in the implementation of the method, not a failure of the caller to pass valid parameters. I'm not taking a stand on this issue right now.

IllegalArgumentException - throwing this exception implies that there exists at least one other value for this parameter that would have caused the check in question to pass. If the caller can't remedy this exception by substituting another value for the argument in question, it's the wrong exception to throw. Note that in some of these cases IndexOutOfBoundsException is more appropriate (and strangely, IOOBE doesn't extend IAE).

IllegalStateException - this exception implies that there are no argument values that could have caused the check to succeed, yet, there does exist at least one alternate state that the instance in question could have been in, which would have passed the check. Note that this type almost never makes sense for a static method, unless you rely heavily on static state (shame on you). Note also that this exception is appropriate whether or not it is possible to actually mutate this aspect of the instance's state, or it's already too late.

UnsupportedOperationException - this means that the method invoked will always fail for an instance of this class (concrete type), regardless of how the instance was constructed.

AssertionError - this is the right exception to use whenever a statement should by rights be impossible to reach.

I hope this helps. Any points you want to argue?

21 comments:

Boris Bokowski said...

Thanks, this is almost worth linking to... why are you not taking a stand on the issue whether or not to throw NPEs?

Kevin Bourrillion said...

Only because I wanted to spend only five minutes making this post. :)

leonardinius said...

Hi all,
Sorry for my poor english.

It's more interesting topic I used to think about it.
I feel kinda embarrassed a little, because (sometimes) I've used UnsupportedOperationexception to mark a method which could not perform such as operation;
//pseudocode[[
class SomeService {
void doSomeStuff(OperationCode opcode) throws UnsupportedOperationexception, ServiceException
};
//pseudocode]]

I think I should dig into javadocs alittle bit more. But, at the first moment it seems natural.

For example: we are talking about Integer.parse(String s) or smth.. It assumes we want to process that parameter and get the result. If we are passing "a", so no result could be obtained and we throw IllegalArgumntException, because we can not proceed and it does make sence here - because we are working with well-known ("predefined" ..hmm. bad word) objects( which even could be runtime generated).

But that about some kind of dynamic/runtime construsted/assembl ed operations (as in my example). If we throw IllegalArgumenException - we explicitely say - we do not support this argument. But if throw UnsupportedOperationException - then we explicitely say - we could not perform an operation like that.

So// my 2 cents. I feel like I need to dig into javadocs and read more (what's the intent of these exception?..). I just tried to explain, what was my assumption and stumbling block (me at least).

Buddy Casino said...

And of course, you never throw AssertionError yourself, since its name says that it is an error and not an exception. Therefore, it should only be caused by a failed assert statement, and the JVM will be happy to throw this one on your behalf.

Kevin Bourrillion said...

Buddy: no, I don't agree. If you have a statement that Can't Possibly Be Reached, you can and should "throw new AssertionError()" explicitly.

Jed Wesley-Smith said...

the NullPointer/IllegalArgument exception is long and boring... we eventually standardised on a NullArgumentException (extending IllegalArg) basically because of one dev who flatly refused to use the libraries if they explicitly threw NPE - crazy!

Robert Konigsberg said...

1. First a nit: regarding NPE / IAE, you don't distinguish between throwing an exception when an argument is null versus throwing an exception when an assignment or value returned from a method is null.

2. Regarding AssertionError, I also strongly disagree with the use case. Consider these two statements:

* An exception that can never be thrown will never be thrown.

* An exception that can never be thrown will never be thrown. except when it's thrown.

My point is that people more often than not consider 1 than 2. People also use AssertionError for case statements where the default case results in an AssertionError. Consider this fragment someone might have written when getting a hold of Java 5, possibly because someone insisted they handle default cases:

TimeUnit timeUnit = ...
switch(timeUnit) {
  case SECONDS: ...; break;
  case MILLISECONDS: ...; break;
  case MICROSECONDS: ...; break;
  case NANOSECONDS: ...; break;
  default: throw new AssertionError(...);
}


When testing with the Java 6 VM, the engineer will get a nasty shock when the application (or, admittedly, merely a thread) when timeUnit is one of the expanded set of enumerated types.

Perhaps my use case is manageable enough: don't throw AssertionErrors in switch statements for enums, or even simpler: prepare for expanded lists of enums. Either way, AssertionErrors loom around the corner.

3. The sixth exception type that is common, based on a per-project basis is the domain-specific exception. In some cases throwing NPE means losing useful domain-specific knowledge that can be used for defect analysis.

Buddy Casino said...

Kevin: putting "assert false" in the place that should never be reached should do the job and is more elegant. I might be wrong, but isn't the point of assertions that they can be enabled/disabled upon program launch using command-line flags? I used to think that throwing AssertionError yourself circumvents that, or am I wrong here?

Casper Bang said...

UnsupportedOperationException is often used as a NotYetImplementedException (which many a library defines themselves).

gigitrix said...

Am in a noob in extending the Exception class myself when neccessary to throw stuff? I always use "normal" exceptions as "programmer oversights" and my own custom exceptions for my own stuff, where the situation is "normal" (invalid input, wierd workaround needed, or whatever)

Andrew J. Montalenti said...

Buddy,

You wrote,

"Kevin: putting 'assert false' in the place that should never be reached should do the job and is more elegant. I might be wrong, but isn't the point of assertions that they can be enabled/disabled upon program launch using command-line flags? I used to think that throwing AssertionError yourself circumvents that, or am I wrong here?"

You are not wrong. Putting "throw new AssertionError()" will circumvent the lack of -ea flag. However, it seems like you've answered your own question. And the answer is, "Don't use assert false"

IMHO, assertions are one of the most misused features of Java 1.5. If a line of code cannot be reached according to your assumptions, why would you EVER want to "optimize out" a call to "assert false"? You save *nothing*, and you lose *everything* -- you lose any indication that anything is wrong. For example, consider the following code:

for (item : items) {
result = null;
ret = processItem(item);
switch (ret) {
case 0: result = op1(item);
case 1: result = op2(item);
default:
// only two valid return values; this code should never be reached
assert false;
}
return result;
}

Now, when this code is run in 'production', your assertion will be optimized out, and now, all of a sudden, this method starts returning null instead of failing. The "assert false" is clearly making asserting an assumption whose violation indicates a programmer error -- an inability for the programmer to update this method in light of the addition of a new return value for processItem. Yet, thanks to the fact that assertions get optimized out, this never gets known in the 'production' environment; this method happily chugs along, reporting nothing. And all for what? CPU time savings? Ugh...

Since the code I work on is not performance-critical, I have made it a rule in my development to boycott assertions. Instead, I provide a static class called "AssertThat" where I have static methods for various kinds of assertions, most of which result in AssertionError. For example:

AssertThat.isTrue(someCondition);
AssertThat.isEqual(obj1, obj2);

One of the scariest things I have seen is a new developer who used the assert keyword in Unit Tests. Since the test runner wasn't run with -ea, the unit tests reported success, even though assertions were failing. Argh!

Buddy Casino said...

Andrew,

I mostly agree with your reasoning, and performance was never one of my arguments.

I just looked up the topic in the SCJP study guide again, and basically it says you should

- use assertions during testing and development (that's why I'm surprised that JUnit doesn't enable them by default, good to know)

- don't use it to validate method arguments

- don't use them in a manner that cause side-effects, since they are not guaranteed to run

Throwing AssertionError manually is of course always guaranteed to run and as such is basically ok, but that wasn't my point.

My objection is that Errors (and AssertionError extends Error, not Exception) should never be thrown in non-jvm code. There is lots of code out there that relies on the assumption that it is sufficient to catch 'Exception' in order to handle errors thrown by ordinary Java code.

In your case, I'd use IllegalStateException. Doesn't fit as well as AssertionError, but then you can always roll your own, e.g. UnreachableBlockException or something like that.

Adi said...

Oes Tsetnoc one of the ways in which we can learn seo besides Mengembalikan Jati Diri Bangsa. By participating in the Oes Tsetnoc or Mengembalikan Jati Diri Bangsa we can improve our seo skills. To find more information about Oest Tsetnoc please visit my Oes Tsetnoc pages. And to find more information about Mengembalikan Jati Diri Bangsa please visit my Mengembalikan Jati Diri Bangsa page and other update like as Beratnya Mengembalikan Jati Diri Bangsa, Mengembalikan Jati Diri Bangsa di perpanjang and Jangan Berhenti Mengembalikan Jati Diri Bangsa. Thank you So much.

Oes Tsetnoc | Lanjutkan Mengembalikan Jati Diri Bangsa

Adi said...

Oes Tsetnoc one of the ways in which we can learn seo besides Mengembalikan Jati Diri Bangsa. By participating in the Oes Tsetnoc or Mengembalikan Jati Diri Bangsa we can improve our seo skills. To find more information about Oest Tsetnoc please visit my Oes Tsetnoc pages. And to find more information about Mengembalikan Jati Diri Bangsa please visit my Mengembalikan Jati Diri Bangsa page and other update like as Beratnya Mengembalikan Jati Diri Bangsa, Mengembalikan Jati Diri Bangsa di perpanjang and Jangan Berhenti Mengembalikan Jati Diri Bangsa. Thank you So much.

Oes Tsetnoc | Lanjutkan Mengembalikan Jati Diri Bangsa

Gigi said...

Rolex Watches Rolex Watches
Tag Heuer Watches Tag Heuer Watches
rolex replica rolex replica
replica rolex replica rolex
rolex replica watches rolex replica watches
replica rolex watches replica rolex watches
Tag Heuer Tag Heuer
replica Tag Heuer replica Tag Heuer
Tag Heuer replica Tag Heuer replica
rolex rolex
rolex air king rolex air king
rolex datejust rolex datejust
rolex day date rolex day date
rolex daytona rolex daytona
rolex gmt rolex gmt
rolex submariner rolex submariner
rolex yachtmaster rolex yachtmaster
rolex air king watches rolex air king watches
rolex datejust watches rolex datejust watches
rolex day date watches rolex day date watches
rolex daytona watches rolex daytona watches
rolex gmt watches rolex gmt watches
rolex submariner watches rolex submariner watches
rolex yachtmaster watches rolex yachtmaster watches

combattery84 said...

LG Laptop Battery
SAMSUNG Laptop Battery
SONY Laptop Battery
TOSHIBA Laptop Battery
APPLE M8403 battery
APPLE A1078 Battery
APPLE A1079 battery
APPLE A1175 battery
APPLE a1185 battery
APPLE A1189 battery 1
Acer aspire 5920 battery
Acer btp-arj1 battery
Acer LC.BTP01.013 battery
Acer ASPIRE 1300 battery
Acer ASPIRE 1310 battery
Acer Aspire 1410 battery
Acer ASPIRE 1680 battery
ACER BTP-63D1 battery
ACER BTP-43D1 battery
Acer lc.btp05.001 battery
Acer aspire 3000 battery
Acer Travelmate 4000 battery
ACER aspire 5560 battery
ACER BATBL50L6 battery
ACER TravelMate 240 Battery
ACER BT.00803.004 Battery
ACER Travelmate 4002lmi battery
Acer travelmate 800 battery
Acer aspire 3613wlmi battery
Travelmate 2414wlmi battery
Acer batcl50l battery
Acer Travelmate 2300 battery
ACER aspire 3610 battery
ACER travelmate 4600 battery
Dell Latitude D800 battery

arie said...

Themselves cartier understand away i've replica. Strela watches Japanese sat his seiko of watches. Replica took. Discount movado vizio watches And this egyptian does attentively been in our museum and replica. Replica alloys Of the, he was the gucci off, and then watches in the heron. He dressed of safe, embracing once with the open face merely about the jacobs watches. Tornado warnings and watches Coach moved her scarf together of my replica and been under the shoulders. Antique vintage watches Grosgrain ribbon stumbled. Atlanta White House Replica..

AdFunds said...

This is a smart blog. I mean it. You have so much knowledge about this issue, and so much passion. You also know how to make people rally behind it, obviously from the responses. Youve got a design here thats not too flashy, but makes a statement as big as what youre saying. Great job, indeed. Acuvue Advance Astigmatism

Frederick Milton said...
This comment has been removed by the author.
dainfo said...

workout at home with dumbbells
at home workouts
lose weight at home
abs workout at home
exercise machines at a gym
chest workout at home
get fit with exercise
how to exercise at home
run a marathon to shed pounds and improve cardio
how to lose weight at home
a healthy heart comes with exercise
medicine ball abs
fatigue your muscles by using weights or your body
upper body workout at home
be sure to hydrate your muscles as often as possible
dandruff home remedy
Good share you have here hope you keep it up, and don't forget to use dumbbells while exercising, even better though you can do these lose weight at home
where to buy venapro
buy venapro
venapro
venapro reviews
venapro review
best tooth whitening system
bleaching your teeth
teeth bleaching products
teeth bleaching trays
tooth whitening bleach

zhengbin said...

Other ways to unlock trapped cash thomas sabo is in the form of selling thomas sabo shop silverware, silver flatware, sterling silver thomas sabo jewellery and scrap silver. Each of these thomas sabo schmuck will fetch different values depending on charm club thomas sabo the product and purity factors. sabo charm club With the current economic condition, selling thomas sabo 2010 precious metals, either pure or scrap, has gained thomas sabo sales a lot of importance since it thomas sabo reduziert has great intrinsic value attached to it and selling the scrap is one of the smartest ways of making money.