Java Exception Naming Conventions - java

In Java, is there a semantic difference between using "Illegal" (as in IllegalArgumentException) versus "Invalid" (as in javax.activity.InvalidActivityException)?
During the course of an assignment it became useful to write a subclass of IllegalArgumentException to represent a series of input characters that cannot be tokenized, and I'm wondering whether convention says to use InvalidTokenException or IllegalTokenException.
The only difference I can find so far is that java.lang seems to prefer "Illegal" while javax.* prefers "Invalid". However, there is also java.security.InvalidParameterException which is a subclass of IllegalArgumentException.

You can have legal usage of an API and still have invalid data; it is all semantics.

javax.activity.InvalidActivityException is inherited from java.rmi.RemoteException and you probably don't want this dependency. See also Javadoc
EDIT both Invalid and Illegal are used synonymously it makes no differency in semantics, just the technical issues mentioned above.
EDIT: From Postgres Documentation Section 45.3.14. Tricky words to avoid:
Illegal. "Illegal" stands for a violation of the law, the rest is "invalid". Better yet, say why it's invalid.

AFAIK, IllegalArgumentException should only be used when you want to signal the incorrect use of an API method call. What it appears you are describing is a scenario when the API has been used incorrectly, so I think an IllegalArgumentException would be the better choice.

Related

Why does ImmutableCollection.contains(null) fail?

Question ahead:
why does in Java the call coll.contains(null) fail for ImmutableCollections?
I know, that immutable collections cannot contain null-elements, and I do not want to discuss whether that's good or bad.
But when I write a Function, that takes a (general, not explicit immutable) Collection, it fails upon checking for nulls. Why does the implementation not return false (which is actually the 'correct' answer)?
And how can I properly check for nulls in a Collection in general?
Edit:
with some discussions (thanks to the commenters!) I realized, that I mixed up two things: ImmutableCollection from the guava library, and the List returned by java.util.List.of, being some class from ImmutableCollections. However, both classes throw an NPE on .contains(null).
My problem was with the List.of result, but technically the same would happen with guaves implementation. [edit: It does not]
I am distressed by this discussion!
Collections that do this have been a pet peeve of mine since before I wrote the first collections that eventually became Guava. If you find any Guava collection that throws NPE just because you asked it a perfectly innocent question like .contains(null), please file a bug! We hate that crap.
EDIT: I was so distressed that I had to go back to look at my 2007 changelist that first created ImmutableSet and saw literally this:
#Override public boolean contains(#Nullable Object target) {
if (target == null) {
return false;
}
ahhhhh.
why does in Java the call coll.contains(null) fail for ImmutableCollections?
Because the design team (the ones who have created guava) decided that, for their collections, null is unwanted, and therefore any interaction between their collections and a null check, even in this case, should just throw to highlight to the programmer, at the earliest possible opportunity, that there is a mismatch. Even where the established behaviour (as per the existing implementations in the core runtime itself, such as ArrayList and friends, as well as the javadoc), rather explicitly go the other way and say that a non-sequitur check (is this pear part of this list of apples?) strongly suggests that the right move is to just return false and not throw.
In other words, guava messed up. But now that they have done so, going back is potentially backwards compatibility breaking. It really isn't very - you are replacing an exception thrown with a false return value; presumably code could be out there that relies on the NPE (catching it and doing something different from what the code would do had contains(null) returned false instead of throwing) - but that's a rare case, and guava breaks backwards compatibility all the time.
And how can I properly check for nulls in a Collection in general?
By calling .contains(null), just as you are. The fact that guava doesn't do it right doesn't change the answer. You might as well ask 'how do I add elements to a list', and counter the answer of "well, you call list.add(item) to do that" with: Well, I have this implementation of the List interface that plays Rick Astley over the speaker instead of adding to the list, so, I reject your answer.
That's.. how java and interfaces work: You can have implementations of them, and the only guardianship that they do what the interface dictates they must, is that the author understands there is a contract that needs to be followed.
Now, normally a library so badly written they break contract for no good reason*, isn't popular. But guava IS popular. Very popular. That gets at a simple truth: No library is perfect. Guava's API design is generally quite good (in my opinion, vastly superior to e.g. Apache commons libraries), and the team actively spends a lot of time debating proper API design, in the sense that the code that one would write using guava is nice (as defined by: Easy to understand, has few surprises, easy to maintain, easy to test, and probably easy to mutate to deal with changing requirements - the only useful definition for nebulous terms like 'nice' or 'elegant' code - it's code that does those things, anything else is pointless aesthetic drivel). In other words, they are actively trying, and they usually get it right.
Just, not in this case. Work around it: return item != null && coll.contains(item); will get the job done.
There is one major argument in favour of guava's choice: They 'contract break' is an implicit break - one would expect that .contains(null) works, and always returns false, but it's not explicitly stated in the javadoc that one must do this. Contrast to e.g. IdentityHashMap, which uses identity equivalence (a==b) and not value equality (a.equals(b)) in its .containsKey etc implementations, which explicitly goes against the javadoc contract as stated in the j.u.Map interface. IHM has an excellent reason for it, and highlights the discrepancy, plus explains the reason, in the javadoc. Guava isn't nearly as clear about their bizarre null behaviour, but, here's a crucial thing about null in java:
Its meaning is nebulous. Sometimes it means 'empty', which is bad design: You should never write if (x == null || x.isEmpty()) - that implies some API is badly coded. If null is semantically equivalent to some value (such as "" or List.of()), then you should just return "" or List.of(), and not null. However, in such a design, list.contains(null) == false) would make sense.
But sometimes null means not found, irrelevant, not applicable, or unknown (for example, if map.get(k) returns null, that's what it means: Not found. Not 'I found an empty value for you'). This matches with what NULL means in e.g. SQL. In all those cases, .contains(null) should be returning neither true nor false. If I hand you a bag of marbles and ask you if there is a marble in there that is grue, and you have no idea what grue means, you shouldn't answer either yes or no to my query: Either answer is a meaningless guess. You should tell me that the question cannot be answered. Which is best represented in java by throwing, which is precisely what guava does. This also matches with what NULL does in SQL. In SQL, v IN (x) returns one of 3 values, not 2 values: It can resolve to true, false, or null. v IN (NULL) would resolve to NULL and not false. It is answering a question that can't be answered with the NULL value, which is to be read as: Don't know.
In other words, guava made a call on what null implies which evidently does not match with your definitions, as you expect .contains(null) to return false. I think your viewpoint is more idiomatic, but the point is, guava's viewpoint is different but also consistent, and the javadoc merely insinuates, but does not explicitly demand, that .contains(null) returns false.
That's not useful whatsoever in fixing your code, but hopefully it gives you a mental model, and answers your question of "why does it work like this?".

Why using error code (such as -1) is not efficient than using exception?

In the JLS8, chapter "Exceptions" (here), I saw that:
Explicit use of throw statements provides an alternative to the
old-fashioned style of handling error conditions by returning funny
values, such as the integer value -1 where a negative value would not
normally be expected. Experience shows that too often such funny
values are ignored or not checked for by callers, leading to programs
that are not robust, exhibit undesirable behavior, or both.
Actually, I'm not clear about 2 issues following:
(1) "such as the integer value -1 where a negative value would not normally be expected", why "a negative value would not normally be expected"? Follow my knowledge, we often use return value "-1" for an error, abnormal event,... or something "not good".
(2) "Experience shows that too often such funny values are ignored or not checked for by callers, leading to programs that are not robust, exhibit undesirable behavior, or both.". What "funny values are ignored or not checked for by callers, leading to programs that are not robust, exhibit undesirable behavior, or both" means? I don't understant this issue...Please help me to clarify and (if yes) give me an example to demonstrate
Thank you so much
A common example is: people not checking the contents of a string, but blindly calling indexOf() - and not taking into account that the "thing searched for" isn't in that string, so the returned result is -1.
At least when using checked exception the programmer must do something about a potential exception thrown from some code that his code is using. For return values, you can completely ignore them - just a bit easier therefore.
On the other hand, many people argue that the idea of checked exception didn't live up to its promise - and are therefore advocating the usage of unchecked exceptions. Or alternatively, as companies such as google propose: the usage of more sophisticated "return value classes".
Long story short:
by the nature of the language exceptions should be seen as the primary mean to communicate severe exceptional conditions
but that doesn't mean that using numeric return codes is not possible or completely discouraged.
Please help me to clarify and (if yes) give me an example to demonstrate:
For example Class.getResourceAsStream(String) returns null if it cannot find the resource, rather than throwing an exception. This is clearly documented in the javadocs.
However, lots of people don't read the documentation, and don't check the result of a getResourceAsStream call. As a result, when the resource is missing, they use the null and get an unexpected NullPointerException.
Another common example is ServletRequest.getParameter(String).
If you analysed the NPE Q's on StackOverflow, you would find that a significant number of them are caused by people not checking the results of the above two methods. (If you don't believe me, the raw questions are available for you to analyse!)
Why using error code (such as -1) is not efficient than using exception?
The text you quoted doesn't say that. And it is probably not true. In fact, the using an error code is (classically) more efficient in many cases. However, with recent JIT compiler improvements, the overheads of exceptions and exception handling have been significantly reduced for typical use-cases.
Summary:
People are lazy. But you knew that!
People are careless. But you knew that!
APIs that require people to check returned values are less robust than those that throw (checked) exceptions ... because people write code that doesn't check return codes. Why? Because people are lazy, careless or both!
Admittedly, there are pragmatic reasons not to throw exceptions. However it is a trade-off of robustness vs efficiency vs forcing the programmer to deal with checked exceptions.
The text you quoted is not trying to tell you use exceptions always. Rather it is explaining the reasons that exceptions are part of the Java language.
You may disagree, but ... frankly ... it is not a topic that is worth debating. Exceptions (checked / unchecked, etc) are so hard-baked into the Java language that it would be impossible to change.
(1) "such as the integer value -1 where a negative value would not normally be expected", why "a negative value would not normally be expected"?
It is a proven fact (see below) that people don't always check return values.
Follow my knowledge, we often use return value "-1" for an error, abnormal event,... or something "not good".
True. And exceptions provide an alternative.
What "funny values are ignored or not checked for by callers
'Funny values' such as -1. There are examples posted here every hour of every day.
leading to programs that are not robust, exhibit undesirable behavior, or both" means?
It means that programs that ignore 'funny values' aren't robust or exhibit undesirable behaviour ... and give rise to trivial questions on this site.
I don't understand this issue...Please help me to clarify and (if yes) give me an example to demonstrate.
Try this search for hundreds of examples.
When a method return an int, the caller have to check if it is an error code. But if here is no expected range of returned value, how could you specify an error signal value?
Let us say what "error code" should a parseInt method return?
And if the caller "forgets" to check the returned value, the error could go unnoticed.
However if an exception is declared, the caller must check and handle it, by catching it or declaring i in throws...

Would it be a good idea if compiler resolved nulls when Optional<Object> is expected as argument?

That would be so obviously useful that I am starting to think I am missing a rationale to avoid it, since I am sure Oracle would have made it that way. It would be the most valuable feature on Optional for me.
public class TestOptionals{
public static void main(String[] args) {
test(null);
}
public static void test(Optional<Object> optional){
System.out.println(optional.orElse(new DefaultObject()));
}
}
(This throws a NullPointerException)
Without that feature I see too verbose using Optional for the argument.
I prefer a simple Object optional signature and
checking it by if (null = optional) that creating the object Optional for comparing later. It is not valuable if that doesn't help you checking the null
There was a HUGE discussion of Optional on all the various Java mailing lists, comprising hundreds of messages. Do a web search for
site:mail.openjdk.java.net optional
and you'll get links to lots of them. Of course, I can't even hope to summarize all the issues that were raised. There was a lot of controversy, and there was quite a breadth of opinion about how much "optionality" should be added to the platform. Some people thought that a library solution shouldn't be added at all; some people thought that a library solution was useless without language support; some people thought that a library solution was OK, but there was an enormous amount of quibbling about what should be in it; and so forth. See this message from Brian Goetz on the lambda-dev mailing list for a bit of perspective.
One pragmatic decision made by the lambda team was that any optional-like feature couldn't involve any language changes. The language and compiler team already had its hands full with lambda and default methods. These of course were the main priorities. Practically speaking, the choices were either to add Optional as a library class or not at all.
Certainly people were aware of other languages' type systems that support option types. This would be a big change to Java's type system. The fact is that for most of the past 20 years, reference types have been nullable, and there's been a single, untyped null value. Changing this is a massive undertaking. It might not even be possible to do this in a compatible way. I'm not an expert in this area, but most such discussions have tended to go off into the weeds pretty quickly.
A smaller change that might be more tractable (also mentioned by Marko Topolnik) is to consider the relationship between reference types and Optional as one of boxing, and then bring in the support for autoboxing/autounboxing that's already in the language.
Already this is somewhat problematic. When auto(un)boxing was added in Java 5, it made a large number of cases much nicer, but it added a lot of rough edges to the language. For example, with auto-unboxing, one can now use < and > to compare the values of boxed Integer objects. Unfortunately, using == still compares references instead of values! Boxing also made overload resolution more complicated; it's one of the most complicated areas of the language today.
Now let's consider auto(un)boxing between reference types and Optional types. This would let you do:
Optional<String> os1 = "foo";
Optional<String> os2 = null;
In this code, os1 would end up as a boxed string value, and os2 would end up as an empty Optional. So far, so good. Now the reverse:
String s1 = os1;
String s2 = os2;
Now s1 would get the unboxed string "foo", and s2 would be unboxed to null, I guess. But the point of Optional was to make such unboxing explicit, so that programmers would be confronted with a decision about what to do with an empty Optional instead of having it just turn into null.
Hmmm, so maybe let's just do autoboxing of Optional but not autounboxing. Let's return to the OP's use case:
public static void main(String[] args) {
test(null);
}
public static void test(Optional<Object> optional) {
System.out.println(optional.orElse(new DefaultObject()));
}
If you really want to use Optional, you can manually box it one line:
public static void test(Object arg) {
Optional<Object> optional = Optional.ofNullable(arg);
System.out.println(optional.orElse(new DefaultObject()));
}
Obviously it might be nicer if you didn't have to write this, but it would take an enormous amount of language/compiler work, and compatibility risk, to save this line of code. Is it really worth it?
What seems to be going on is that this would allow the caller to pass null in order to have some specific meaning to the callee, such as "use the default object" instead. In small examples this seems fine, but in general, loading semantics onto null increasingly seems like a bad idea. So this is an additional reason not to add specific language support for boxing of null. The Optional.ofNullable() method mainly is there to bridge the gap between code that uses null and code that uses Optional.
If you are committed to using the Optional class, then see the other answers.
On the other hand, I interpreted your question as, "Would it be a good idea to avoid the syntactic overhead of using Optional while still obtaining a guarantee of no null pointer exceptions in your code?" The answer to this question is a resounding yes. Luckily, Java has a feature, type annotations, that enables this. It does not require use of the the Optional class.
You can obtain the same compile-time guarantees, without adding Optional to your code and while retaining backward compatibility with existing code.
Annotate references that might be null with the #Nullable type
annotation.
Run a compiler plugin such as the Checker Framework's Nullness Checker.
If the plugin issues no errors, then you know that your code always checks for null where it needs to, and therefore your code never issues a null pointer exception exception at run time.
The plugin handles the special cases mentioned by #immibis and more, so your code is much less verbose than code using Optional. The plugin is compatible with normal Java code and does not require use of Java 8 as Optional does. It is in daily use at companies such as Google.
Note that this approach requires you to supply a command-line argument to the compiler to tell it to run the plugin. Also note that this approach does not integrate with Optional; it is an alternate approach.

Some java method are null safe, some are not, how do I know?

Some java method is null safe, but some are not. How to distinguish them?
I assume you mean in terms of the parameters? The documentation should state whether or not the arguments can be null, and when they can be null, what semantic meaning is inferred from nullity.
Unfortunately not all documentation is clear like this - and likewise it may not specify whether the return value might be null or not... in which case all you can do is experiment or look at the source code where possible :(
In general, I would suggest that you assume that you cannot pass null as a parameter unless the documentation clearly states that you can and what the corresponding behaviour is.
A problem with taking the default assumption that a parameter might be "null-safe" is that, even if that turns out to be true, it's not always clear without documentation what the corresponding behaviour actually is. "Not throwing an exception" doesn't actually indicate what alternative behaviour/default parameter/assumptions are then going to occur instead.
If you're designing an API, then where is's practical, I would suggest not actually encouraging null to be passed as a parameter to exposed methods/constructors, but rather have separate method signatures that include or not the various optional parameters. And in any case, you may then need to document in some way what actual behaviour is being taken to make up for the missing parameter.
If you're lucky, the parameter will be documented or annotated, or both. Unfortunately, most Java APIs lack both.
Some static analysis tools can use annotations to check whether you're passing a null value inappropriately. For example, the FindBugs tool includes support for these annotations:
#NonNull - The value must not be null
#CheckForNull - The value may contain null.
#Nullable - Whether the value may contain null or not depends on context.
Read the javadocs of the methods you are trying to call. If the javadocs don't specify this, then trial and error in a unit test is probably your best bet.

Defensive Programming: Guidelines in Java

I’m from a .NET background and now dabbling in Java.
Currently, I’m having big problems designing an API defensively against faulty input. Let’s say I’ve got the following code (close enough):
public void setTokens(Node node, int newTokens) {
tokens.put(node, newTokens);
}
However, this code can fail for two reasons:
User passes a null node.
User passes an invalid node, i.e. one not contained in the graph.
In .NET, I would throw an ArgumentNullException (rather than a NullReferenceException!) or an ArgumentException respectively, passing the name of the offending argument (node) as a string argument.
Java doesn’t seem to have equivalent exceptions. I realize that I could be more specific and just throw whatever exception comes closest to describing the situation, or even writing my own exception class for the specific situation.
Is this the best practice? Or are there general-purpose classes similar to ArgumentException in .NET?
Does it even make sense to check against null in this case? The code will fail anyway and the exception’s stack trace will contain the above method call. Checking against null seems redundant and excessive. Granted, the stack trace will be slightly cleaner (since its target is the above method, rather than an internal check in the HashMap implementation of the JRE). But this must be offset against the cost of an additional if statement, which, furthermore, should never occur anyway – after all, passing null to the above method isn’t an expected situation, it’s a rather stupid bug. Expecting it is downright paranoid – and it will fail with the same exception even if I don’t check for it.
[As has been pointed out in the comments, HashMap.put actually allows null values for the key. So a check against null wouldn’t necessarily be redundant here.]
The standard Java exception is IllegalArgumentException. Some will throw NullPointerException if the argument is null, but for me NPE has that "someone screwed up" connotation, and you don't want clients of your API to think you don't know what you're doing.
For public APIs, check the arguments and fail early and cleanly. The time/cost barely matters.
Different groups have different standards.
Firstly, I assume you know the difference between RuntimeExceptions (unchecked) and normal Exceptions (checked), if not then see this question and the answers. If you write your own exception you can force it to be caught, whereas both NullPointerException and IllegalArgumentException are RuntimeExceptions which are frowned on in some circles.
Secondly, as with you, groups I've worked with but don't actively use asserts, but if your team (or consumer of the API) has decided it will use asserts, then assert sounds like precisely the correct mechanism.
If I was you I would use NullPointerException. The reason for this is precedent. Take an example Java API from Sun, for example java.util.TreeSet. This uses NPEs for precisely this sort of situation, and while it does look like your code just used a null, it is entirely appropriate.
As others have said IllegalArgumentException is an option, but I think NullPointerException is more communicative.
If this API is designed to be used by outside companies/teams I would stick with NullPointerException, but make sure it is declared in the javadoc. If it is for internal use then you might decide that adding your own Exception heirarchy is worthwhile, but personally I find that APIs which add huge exception heirarchies, which are only going to be printStackTrace()d or logged are just a waste of effort.
At the end of the day the main thing is that your code communicates clearly. A local exception heirarchy is like local jargon - it adds information for insiders but can baffle outsiders.
As regards checking against null I would argue it does make sense. Firstly, it allows you to add a message about what was null (ie node or tokens) when you construct the exception which would be helpful. Secondly, in future you might use a Map implementation which allows null, and then you would lose the error check. The cost is almost nothing, so unless a profiler says it is an inner loop problem I wouldn't worry about it.
In Java you would normally throw an IllegalArgumentException
If you want a guide about how to write good Java code, I can highly recommend the book Effective Java by Joshua Bloch.
It sounds like this might be an appropriate use for an assert:
public void setTokens(Node node, int newTokens) {
assert node != null;
tokens.put(node, newTokens);
}
Your approach depends entirely on what contract your function offers to callers - is it a precondition that node is not null?
If it is then you should throw an exception if node is null, since it is a contract violation. If it isnt then your function should silently handle the null Node and respond appropriately.
I think a lot depends on the contract of the method and how well the caller is known.
At some point in the process the caller could take action to validate the node before calling your method. If you know the caller and know that these nodes are always validated then i think it is ok to assume you'll get good data. Essentially responsibility is on the caller.
However if you are, for example, providing a third party library that is distributed then you need to validate the node for nulls, etcs...
An illegalArugementException is the java standard but is also a RunTimeException. So if you want to force the caller to handle the exception then you need to provided a check exception, probably a custom one you create.
Personally I'd like NullPointerExceptions to ONLY happen by accident, so something else must be used to indicate that an illegal argument value was passed. IllegalArgumentException is fine for this.
if (arg1 == null) {
throw new IllegalArgumentException("arg1 == null");
}
This should be sufficient to both those reading the code, but also the poor soul who gets a support call at 3 in the morning.
(and, ALWAYS provide an explanatory text for your exceptions, you will appreciate them some sad day)
like the other : java.lang.IllegalArgumentException.
About checking null Node, what about checking bad input at the Node creation ?
I don't have to please anybody, so what I do now as canonical code is
void method(String s)
if((s != null) && (s instanceof String) && (s.length() > 0x0000))
{
which gets me a lot of sleep.
Others will disagree.

Categories

Resources