Update: Pattern matching for switch arrived in Java 21.
tl;dr
👉 switch expressions != pattern matching with switch
You are mixing up the relatively new feature of switch expressions with the still-not-released feature of pattern matching with switch.
The switch feature in Java has been evolving through 3 phases, two completed:
- ☑️
switchstatement (original feature in Java 1) - ☑️
switchexpression (Java 14+) - ❌ Pattern matching for
switch, includingcase null(previewed in Java 17, 18, 19, & 20)
Do not conflate switch expressions with pattern matching
Classic switch
Understand that historically, the Java switch statement has been hostile to null checks. See this Question, How to use null in switch. As shown there, code such as this:
switch ( i ) {
case null:
doSomething0();
break;
}
… was not possible.
switch expressions
Fast forward to Java 14, when switch expressions was added to Java. A switch can return a value. See JEP 361: Switch Expressions.
The switch expressions feature provides the syntax seen in your first code example:
return switch ( testEnum ) {
case FOO -> newFoo();
case BAR -> newBar();
}
But read the JEP. No mention of null — « crickets ».
Pattern matching for switch
Fast forward further, to JEP 406: Pattern Matching for switch (Preview). Note that this is a preview feature in Java 17, not a final, officially released feature. (To understand how preview features work, read JEP 12: Preview Features.)
👉 In that JEP 406, notice its second goal: Allow the historical null-hostility of switch to be relaxed when desired.
Now search that page for “null” — 73 hits! That page explains the former policy of the Java language:
Traditionally,
switchstatements and expressions throwNullPointerExceptionif the selector expression evaluates tonull…
Notice the mention of statements, the original switch syntax, and additionally expressions, the new syntax used in your code. In both cases, null check was forbidden.
That page goes on to explain the changes that motivate the inclusion of support for null checks. Read the JEP for well-written details.
👉 The upshot is that you can use case null in a switch in Java 17 — but only if you go out of your way to enable the preview feature.
Arrived in Java 21
This feature arrived in Java 21. See JEP 441: Pattern Matching for switch.
Example
Let's try this code example. Notice how we use plain old syntax here, without the ->. The arrow operator is not related to our discussion here.
String x = null;
switch ( x )
{
case "starburst":
System.out.println( "Is starburst." );
break;
case null:
System.out.println( "Whoops, null." );
break;
default:
System.out.println( "Some other value found." );
break;
}
Answer from Basil Bourque on Stack OverflowUpdate: Pattern matching for switch arrived in Java 21.
tl;dr
👉 switch expressions != pattern matching with switch
You are mixing up the relatively new feature of switch expressions with the still-not-released feature of pattern matching with switch.
The switch feature in Java has been evolving through 3 phases, two completed:
- ☑️
switchstatement (original feature in Java 1) - ☑️
switchexpression (Java 14+) - ❌ Pattern matching for
switch, includingcase null(previewed in Java 17, 18, 19, & 20)
Do not conflate switch expressions with pattern matching
Classic switch
Understand that historically, the Java switch statement has been hostile to null checks. See this Question, How to use null in switch. As shown there, code such as this:
switch ( i ) {
case null:
doSomething0();
break;
}
… was not possible.
switch expressions
Fast forward to Java 14, when switch expressions was added to Java. A switch can return a value. See JEP 361: Switch Expressions.
The switch expressions feature provides the syntax seen in your first code example:
return switch ( testEnum ) {
case FOO -> newFoo();
case BAR -> newBar();
}
But read the JEP. No mention of null — « crickets ».
Pattern matching for switch
Fast forward further, to JEP 406: Pattern Matching for switch (Preview). Note that this is a preview feature in Java 17, not a final, officially released feature. (To understand how preview features work, read JEP 12: Preview Features.)
👉 In that JEP 406, notice its second goal: Allow the historical null-hostility of switch to be relaxed when desired.
Now search that page for “null” — 73 hits! That page explains the former policy of the Java language:
Traditionally,
switchstatements and expressions throwNullPointerExceptionif the selector expression evaluates tonull…
Notice the mention of statements, the original switch syntax, and additionally expressions, the new syntax used in your code. In both cases, null check was forbidden.
That page goes on to explain the changes that motivate the inclusion of support for null checks. Read the JEP for well-written details.
👉 The upshot is that you can use case null in a switch in Java 17 — but only if you go out of your way to enable the preview feature.
Arrived in Java 21
This feature arrived in Java 21. See JEP 441: Pattern Matching for switch.
Example
Let's try this code example. Notice how we use plain old syntax here, without the ->. The arrow operator is not related to our discussion here.
String x = null;
switch ( x )
{
case "starburst":
System.out.println( "Is starburst." );
break;
case null:
System.out.println( "Whoops, null." );
break;
default:
System.out.println( "Some other value found." );
break;
}
This command line works for me:
$ javac -version
javac 17.0.3
$ javac -source 17 -Xlint:preview --enable-preview org/kablambda/Main.java
org/kablambda/Main.java:10: warning: [preview] null in switch cases is a preview feature and may be removed in a future release.
case null -> "c";
^
1 warning
nullpointerexception - How do I avoid checking for nulls in Java? - Stack Overflow
java - Is Eclipse's null check analysis confused by JUnit's 'fail'? - Stack Overflow
How to handle null values in Java (eclipse IDE) - Stack Overflow
java - Why Eclipse null analysis ignore null-checking statement: if (someObject != null) {...}, when someObject is a field-scope variable? - Stack Overflow
You can try changing your eclipse configuration first rather than using a plugin. Try setting Windows > Preferences > Java > Compiler > Errors/Warnings > Potential Programming Problems > Potential Null Pointer Access to anything besides ignore.
As a side note, always try to use a defensive programming approach if you feel like the code you're writing has many potential exception/error courses.
In my opinion the nullpointer exception is the best null check. You should always test every method/function with jUnit and then you see wether there are some null errors.
This to me sounds like a reasonably common problem that junior to intermediate developers tend to face at some point: they either don't know or don't trust the contracts they are participating in and defensively overcheck for nulls. Additionally, when writing their own code, they tend to rely on returning nulls to indicate something thus requiring the caller to check for nulls.
To put this another way, there are two instances where null checking comes up:
Where null is a valid response in terms of the contract; and
Where it isn't a valid response.
(2) is easy. As of Java 1.7 you can use Objects.requireNonNull(foo). (If you are stuck with a previous version then assertions may be a good alternative.)
"Proper" usage of this method would be like below. The method returns the object passed into it and throws a NullPointerException if the object is null. This means that the returned value is always non-null. The method is primarily intended for validating parameters.
public Foo(Bar bar) {
this.bar = Objects.requireNonNull(bar);
}
It can also be used like an assertion though since it throws an exception if the object is null. In both uses, a message can be added which will be shown in the exception. Below is using it like an assertion and providing a message.
Objects.requireNonNull(someobject, "if someobject is null then something is wrong");
someobject.doCalc();
Generally throwing a specific exception like NullPointerException when a value is null but shouldn't be is favorable to throwing a more general exception like AssertionError. This is the approach the Java library takes; favoring NullPointerException over IllegalArgumentException when an argument is not allowed to be null.
(1) is a little harder. If you have no control over the code you're calling then you're stuck. If null is a valid response, you have to check for it.
If it's code that you do control, however (and this is often the case), then it's a different story. Avoid using nulls as a response. With methods that return collections, it's easy: return empty collections (or arrays) instead of nulls pretty much all the time.
With non-collections it might be harder. Consider this as an example: if you have these interfaces:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
where Parser takes raw user input and finds something to do, perhaps if you're implementing a command line interface for something. Now you might make the contract that it returns null if there's no appropriate action. That leads the null checking you're talking about.
An alternative solution is to never return null and instead use the Null Object pattern:
public class MyParser implements Parser {
private static Action DO_NOTHING = new Action() {
public void doSomething() { /* do nothing */ }
};
public Action findAction(String userInput) {
// ...
if ( /* we can't find any actions */ ) {
return DO_NOTHING;
}
}
}
Compare:
Parser parser = ParserFactory.getParser();
if (parser == null) {
// now what?
// this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
}
to
ParserFactory.getParser().findAction(someInput).doSomething();
which is a much better design because it leads to more concise code.
That said, perhaps it is entirely appropriate for the findAction() method to throw an Exception with a meaningful error message -- especially in this case where you are relying on user input. It would be much better for the findAction method to throw an Exception than for the calling method to blow up with a simple NullPointerException with no explanation.
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
Or if you think the try/catch mechanism is too ugly, rather than Do Nothing your default action should provide feedback to the user.
public Action findAction(final String userInput) {
/* Code to return requested Action if found */
return new Action() {
public void doSomething() {
userConsole.err("Action not found: " + userInput);
}
}
}
If you use (or planning to use) a Java IDE like JetBrains IntelliJ IDEA, Eclipse or Netbeans or a tool like findbugs then you can use annotations to solve this problem.
Basically, you've got @Nullable and @NotNull.
You can use in method and parameters, like this:
@NotNull public static String helloWorld() {
return "Hello World";
}
or
@Nullable public static String helloWorld() {
return "Hello World";
}
The second example won't compile (in IntelliJ IDEA).
When you use the first helloWorld() function in another piece of code:
public static void main(String[] args)
{
String result = helloWorld();
if(result != null) {
System.out.println(result);
}
}
Now the IntelliJ IDEA compiler will tell you that the check is useless, since the helloWorld() function won't return null, ever.
Using parameter
void someMethod(@NotNull someParameter) { }
if you write something like:
someMethod(null);
This won't compile.
Last example using @Nullable
@Nullable iWantToDestroyEverything() { return null; }
Doing this
iWantToDestroyEverything().something();
And you can be sure that this won't happen. :)
It's a nice way to let the compiler check something more than it usually does and to enforce your contracts to be stronger. Unfortunately, it's not supported by all the compilers.
In IntelliJ IDEA 10.5 and on, they added support for any other @Nullable @NotNull implementations.
See blog post More flexible and configurable @Nullable/@NotNull annotations.
Eclipse has a built in list of a few methods which it knows will not return. This includes the JUnit assertNotNull but does not include fail.
Eclise bug 382069 describes this support.
How is Eclipse supposed to know that? As far as it's concerned this is just another library call.
If you use it like this it should work without a NullPointerException:
Object foo = someMethod();
if (foo == null) {
org.junit.Assert.fail("Jesus Christ what a horrible error!");
} else {
foo.doSomeStuff();
}
Have a look at Optional. Using the sample provided, the following can throw a NPE if any of the methods called returns a null value:
String version = computer.getSoundcard().getUSB().getVersion();
To avoid that or excessive if (x != null) checks, using Optional you can use:
String name = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
You would need to build a custom annotation for this or any purpose of yours. You can create an Annotation for you with @Target(ElementType.PARAMETER) and sue reflection to map it as required. But this is so lengthy process which doesn't need much of your time. Instead just write a method and just call it.
I can't think of an API readily available. As you pointed out, lombok doesn't do that for you.
No, a null check is not needed before using instanceof.
The expression x instanceof SomeClass is false if x is null.
The Java 11 Language Specification expresses this concisely in section 15.20.2, "Type comparison operator instanceof". (Java 17 expresses this less concisely, after the introduction of instanceof pattern matching.)
"At run time, the result of the
instanceofoperator istrueif the value of the RelationalExpression is notnulland the reference could be cast to the ReferenceType without raising aClassCastException. Otherwise the result isfalse."
So if the operand is null, the result is false.
Using a null reference as the first operand to instanceof returns false.
Perhaps you are having an old eclipse version. My eclipse generates this:
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
You are right, if Eclipse does it that way. But it doesn't. On my machine, Eclipse Indigo / Ubuntu, given this Class:
public class Foo {
private String bar;
}
Eclipse would generate the following equals() method:
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
Foo other = (Foo) obj;
if (bar == null) {
if (other.bar != null) return false;
} else if (!bar.equals(other.bar)) return false;
return true;
}
For comparison, here's the equals() method I would write for the same class (using Guava):
@Override
public boolean equals(final Object obj) {
return obj instanceof Foo ? Objects.equal(bar, ((Foo) obj).bar) : false;
// ^--- implicit null check here
}
I use this Eclipse code template to achieve this:
${:import(com.google.common.base.Objects)}
@Override
public boolean equals(final Object obj){
return obj instanceof ${enclosing_type} ? Objects.equal(${field1:field}, ((${enclosing_type}) obj).${field1}) : false;
}
@Override
public int hashCode(){
return Objects.hashCode(${field1});
}
@Override
public String toString(){
return MoreObjects.toStringHelper(this).add("${field1}", ${field1}).toString();
}
Unfortunately, I have to keep one of these around for each cardinality of fields, so I have templates named eq1 (the above), eq2, eq3, eq4 etc. It's a small nuissance, but it's still a lot better than the monster methods generated by Eclipse. Guava docs
Method 4 is best.
if(foo != null && foo.bar()) {
someStuff();
}
will use short-circuit evaluation, meaning it ends if the first condition of a logical AND is false.
The last and the best one. i.e LOGICAL AND
if (foo != null && foo.bar()) {
etc...
}
Because in logical &&
it is not necessary to know what the right hand side is, the result must be false
Prefer to read :Java logical operator short-circuiting
Are there any plans in the works for Java to get null pointer safety at compile time (maybe similar to Kotlin's implementation) in the future? At the moment, I sprinkle "Objects.requireNonNull" in my methods (which admittedly has saved me countless hours of debugging null issues)...but I find this to be inefficient compared to a compile-time solution. I'm also not satisfied with the other run-time solutions of dealing with null such as with the "Optional" type or annotations.
I think Java has been doing great things to close the gap between itself and languages like Kotlin (e.g. records instead of data classes as well as virtual threads instead of coroutines), but I find the lack of compile-time null pointer safety in Java, as well as my lack of being able to find any future plans for it, to be a potential dealbreaker for new projects in which I get to decide the language.