If null is a reasonable input parameter for your method, fix the method. If not, fix the caller. "Reasonable" is a flexible term, so I propose the following test: How should the method hande a null input? If you find more than one possible answer, then null is not a reasonable input.
Answer from user281377 on Stack ExchangeIf null is a reasonable input parameter for your method, fix the method. If not, fix the caller. "Reasonable" is a flexible term, so I propose the following test: How should the method hande a null input? If you find more than one possible answer, then null is not a reasonable input.
Don't use null, use Optional
As you've pointed out, one of the biggest problems with null in Java is that it can be used everywhere, or at least for all reference types.
It's impossible to tell that could be null and what couldn't be.
Java 8 introduces a much better pattern: Optional.
And example from Oracle:
String version = "UNKNOWN";
if(computer != null) {
Soundcard soundcard = computer.getSoundcard();
if(soundcard != null) {
USB usb = soundcard.getUSB();
if(usb != null) {
version = usb.getVersion();
}
}
}
If each of these may or may not return a successful value, you can change the APIs to Optionals:
String name = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
By explicitly encoding optionality in the type, your interfaces will be much better, and your code will be cleaner.
If you are not using Java 8, you can look at com.google.common.base.Optional in Google Guava.
A good explanation by the Guava team: https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
A more general explanation of disadvantages to null, with examples from several languages: https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/
@Nonnull, @Nullable
Java 8 adds these annotation to help code checking tools like IDEs catch problems. They're fairly limited in their effectiveness.
Check when it makes sense
Don't write 50% of your code checking null, particularly if there is nothing sensible your code can do with a null value.
On the other hand, if null could be used and mean something, make sure to use it.
Ultimately, you obviously can't remove null from Java. I strongly recommend substituting the Optional abstraction whenever possible, and checking null those other times that you can do something reasonable about it.
Videos
For starters...the safest way to compare a String against a potentially null value is to put the guaranteed not-null String first, and call .equals on that:
if("constantString".equals(COMPLETEDDATE)) {
// logic
}
But in general, your approach isn't correct.
The first one, as I commented, will always generate a NullPointerException is it's evaluated past country[23] == null. If it's null, it doesn't have a .length property. You probably meant to call country[23] != null instead.
The second approach only compares it against the literal string "null", which may or may not be true given the scope of your program. Also, if COMPLETEDDATE itself is null, it will fail - in that case, you would rectify it as I described above.
Your third approach is correct in the sense that it's the only thing checking against null. Typically though, you would want to do some logic if the object you wanted wasn't null.
Your fourth approach is correct by accident; if COMPLETEDDATE is actually null, the OR will short-circuit. It could also be true if COMPLETEDDATE was equal to the literal "null".
To check null string you can use Optional in Java 8 as below: import Optional
import java.util.Optional;
import it as above
String str= null;
Optional<String> str2 = Optional.ofNullable(str);
then use isPresent() , it will return false if str2 contains NULL otherwise true
if(str2.isPresent())
{
//If No NULL
}
else
{
//If NULL
}
reference: https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
If you're still getting an NPE, then the problem is in getNeighbours and not the second snippet.
this.adjacencyListis null, -OR-this.adjacencyList.get(v)returns null.
Given that you're passing a name to a method that will then do a lookup by node, and that you can't call .get(someNodeRef) on a list, adjacencyList is probably some sort of hashmap, so your names are off and you should rename some things. Map's .get(x) method returns null if an entry is not found, so most likely the culprit is that v isn't in the map at all, and thus .get(v).isEmpty() throws NPE.
The fixes are as follows:
You should NEVER return null when a valid sentinel value that carries the intended semantic meaning is available. A mouthful, but it means here: Why are you returning null when you intend to treat that the exact same way as 'zero nodes'? There is an instance of
Iterable<Node>that properly represents the concept of zero nodes, and it isn'tnull. It'sList.of()or equivalent: An empty list has no nodes. Great. That's what you intended. So return that..get(v).isEmpty()is bad code here, as it would mean an NPE occurs if you ask for a non-existent node. Unless, of course, you want it to work that way. An easy way out is the defaulting mechanism: Call.getOrDefaultinstead:
if (!this.adjacencyList.getOrDefault(v, List.of()).isEmpty()) ....
except, of course, you should never be returning null when you can return an empty list instead, so your getNeighbours method becomes simply:
return adjacencyMap.getOrDefault(v, List.of());
that one-liner will fix all things.
In general, if you are writing code where null is dealt with in some way, and some sentinel value (such as a blank string or an empty list) is dealt with in the same way, your code is badly styled; however you got that null should have gotten you that empty value instead. e.g. if you ever write this:
if (x == null || x.isEmpty()) ...
you messed up. Figure out where you got x from. Update it there, make x the blank sentinel ("" for strings, List.of for lists, etcetera).
That, and use .getOrDefault and other such methods more: Methods that let you provide what should happen when e.g. a key is not found.
You should probably avoid returning null from your getNeighbors method. It's not good practice to return null for Iterables, Iterators and Collections, since an empty iterable would represent the same concept (there is nothing in that adjacency list) without all the dangers of null. And your code would be simpler. You can check if the iterable contains anything and if not then default to the full iterator.