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
Assign null
When we write:
String s = "Hello World!";
s = null;
The String object still exists in memory because this does not delete it. However the garbage collector will clear the object from memory as there is no variable referencing it.
For all practical purposes s = null; deletes the String.
tl;dr
set a String to null in Java?
myString = null ;
declare the variable without initializing it
Uninitialized deaults to null, no String object. Empty reference variable.
String myString ;
You can explicitly assign null. Same effect as line above. No object, empty reference.
String name = null;
Declare and initialize to empty string:
String myString = "" ; // A `String` object containing no characters. Not null.
Details
Before posting here on basic Java Questions, study the Java Tutorials provided by Oracle free of cost.
See the tutorial page on string literals. To quote:
There's also a special
nullliteral that can be used as a value for any reference type.nullmay be assigned to any variable, except variables of primitive types. There's little you can do with anullvalue beyond testing for its presence. Therefore,nullis often used in programs as a marker to indicate that some object is unavailable.
So null is not a piece of text with four characters. The keyword null means “no object at all”, no String, nothing at all, an empty reference.
To test if an object reference variable is null (contains no reference), you have a few choices:
Objects.isNull( myVar )andObjects.nonNull( myVar )null == myVarandnull != myVarmyVar == nullandmyVar != null
I prefer the first, as words are easier to read than mathematical-like symbols.
I was using IntelliJ and it said that a string needed to be initialized in order for the program to work. It suggests I initialize it this way
String example = null;
instead of
String example = "";
Do you agree with this? I've found conflicting information as to whether or not this is a good idea.
string == null compares if the object is null. string.equals("foo") compares the value inside of that object. string == "foo" doesn't always work, because you're trying to see if the objects are the same, not the values they represent.
Longer answer:
If you try this, it won't work, as you've found:
String foo = null;
if (foo.equals(null)) {
// That fails every time.
}
The reason is that foo is null, so it doesn't know what .equals is; there's no object there for .equals to be called from.
What you probably wanted was:
String foo = null;
if (foo == null) {
// That will work.
}
The typical way to guard yourself against a null when dealing with Strings is:
String foo = null;
String bar = "Some string";
...
if (foo != null && foo.equals(bar)) {
// Do something here.
}
That way, if foo was null, it doesn't evaluate the second half of the conditional, and things are all right.
The easy way, if you're using a String literal (instead of a variable), is:
String foo = null;
...
if ("some String".equals(foo)) {
// Do something here.
}
If you want to work around that, Apache Commons has a class - StringUtils - that provides null-safe String operations.
if (StringUtils.equals(foo, bar)) {
// Do something here.
}
Another response was joking, and said you should do this:
boolean isNull = false;
try {
stringname.equalsIgnoreCase(null);
} catch (NullPointerException npe) {
isNull = true;
}
Please don't do that. You should only throw exceptions for errors that are exceptional; if you're expecting a null, you should check for it ahead of time, and not let it throw the exception.
In my head, there are two reasons for this. First, exceptions are slow; checking against null is fast, but when the JVM throws an exception, it takes a lot of time. Second, the code is much easier to read and maintain if you just check for the null pointer ahead of time.
s == null
won't work?
First let's clarify something: You mention that after assigning null to the variable you could forget to initialize it, but by assigning null to it you are in effect initializing it.
public static void main (String args[]){
String s;
System.out.println(s); // compiler error variable may not be initialized
}
vs
public static void main (String args[]){
String s=null;
System.out.println(s); // no compiler error
System.out.println(s.equals("helo")); // but this will generate an exception
}
So after you do String s=null; there's is no way that you could forget to initialize because you did initialize it.
That being clear, I would recommend you to use a "smart default". In your case perhaps the empty string "" would be a good default value if you want to avoid NullPointerException. In the other hand, sometimes it is desirable that the program produce an exception because it indicates something wrong happened under the hood that should not have happened.
In general you want to keep declaration and initialisation as close as possible to minimise exactly the type of problem you're talking about.
There is also the issue of redundant initialisation where the value null you're assigning is never used which is extra code that harms readability even if the redundant assignment is optimised away by the compiler.
Sometimes assigning some sort of default value is unavoidable, for example if you declare before a try catch, initialise inside and use it afterwards. For other types you can often find a more natural default value such as an empty list.