[ACCEPTED]-Exceptions as public classes vs. public static inner classes-exception-handling

Accepted answer
Score: 19

In case the exception is very specific to 6 Foo class, I don't mind keeping it as a public Nested 5 class. And whenever it seems like a time 4 to extract that out, simply extract that 3 out.

In general practice, I have never seen 2 any nested class defined for Exception, though. I 1 also don't know if one exist in Java API.

Score: 12

In my 10+ years experience with Java, I 13 cannot recall coming across an API where 12 a public exception class was defined as 11 a static inner class. I cannot give you 10 a specific reason why it would be a bad 9 idea to do this, but it would certainly 8 make your code unusual.

Why do you feel that it 7 is necessary to do this, given that (apparently) nobody 6 else does? I hope you are not just doing 5 it to be "innovative".

(BTW, I know that 4 some well-known Java APIs use public static 3 inner classes and interfaces for other things. I'm 2 specifically talking about the case of exception 1 classes here.)

Score: 9

I can definitely think of situations where 58 I'd prefer the exception to be a static inner 57 class than merely a class in the same package.

The 56 reasons not to do so seem to be:

  • Coupling the exception to the class that throws it makes it inappropriate to reuse in other contexts
  • Nobody else does it

I do not 55 find either of those arguments at all convincing.

For 54 the first point, why should this hypothetical 53 future opportunity for re-use arise in the 52 same package? This argument leads to the 51 conclusion that we should put all exception 50 classes as high as possible in the package 49 hierarchy so that when we discover a future 48 opportunity to reuse the same exception 47 we don't have to introduce a dependency 46 on where it was originally defined.

But even 45 without the "taken to extremes" point, consider 44 an exception intended to convey that class 43 Foo was given wrong input. If I call it Foo.InvalidInput, the 42 name is short and the association with Foo is 41 impossible to miss. If I put it outside 40 the Foo class and call it FooInvalidCriteria, then I can't reuse 39 it from class Bar anyway, without changing 38 its name (equivalent to changing its location).

But 37 worst is if I leave it outside Foo and keep 36 its name general like InvalidInput. Then when I later 35 realise that Bar might have invalid input too 34 and make it start throwing this exception. Everything 33 compiles and runs fine, only now all the 32 places that were catching InvalidInput and assuming 31 they were handling errors from Foo could now 30 also be handling errors from Bar if Foo happens 29 to use Bar internally in a way that could cause 28 this exception to be thrown. This could 27 easily cause code breakage.

The reality is 26 that taking an exception that was previously 25 conceived as specifically indicating a situation 24 that arises in one class and re-using it 23 as a general error class is an interface change, not 22 just an internal implementation change. To 21 do so correctly in general you must revisit 20 all the sites where the exception is caught 19 and make sure they're still correct, so 18 having the compiler tell you about all the 17 use sites (because you have to change the 16 name and/or import path) is a good thing. Any 15 exception that you might make a static inner 14 class is inappropriate for reuse in other 13 contexts no matter whether you actually 12 make it an inner class or not.

And as for 11 the second dot point... "nobody else does 10 it" never bears on anything. Either it really 9 is the wrong thing to do, so there will 8 be other reasons not to do it, so the "nobody 7 else does it" argument is unnecessary. Or 6 it isn't. And it's not like this particular 5 example would even be terribly complicated 4 and hard to understand, so not even the 3 "it's unexpected so people will have trouble 2 following it even if it's a good idea in 1 theory" argument is very strong.

Score: 3

I'd prefer the (not necessarily public) class 14 within the same package, as a package is 13 a logical group of classes depicting a business 12 model, which the exception belongs to as 11 a technical part.

A user will see immediatelly 10 that there's an exception when he looks 9 at the package and does not need to read 8 the file of class foo, which is better for 7 maintenance and clarity/readability/comprehensional 6 reasons. It's very good to define custom 5 exceptions and to tell the API-user about 4 it!

I'd only use an inner class when it's 3 clearly a private thing of the class in 2 question.

Nevertheless, we're talking here 1 about a mainly conventional issue!

More Related questions