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:

  • ☑️ switch statement (original feature in Java 1)
  • ☑️ switch expression (Java 14+)
  • ❌ Pattern matching for switch, including case 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, switch statements and expressions throw NullPointerException if the selector expression evaluates to null

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 Overflow
Top answer
1 of 3
22

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:

  • ☑️ switch statement (original feature in Java 1)
  • ☑️ switch expression (Java 14+)
  • ❌ Pattern matching for switch, including case 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, switch statements and expressions throw NullPointerException if the selector expression evaluates to null

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;
}
2 of 3
1

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
🌐
javathinking
javathinking.com › blog › error-message-displayed-when-opening-eclipse-an-error-has-occurred-see-the-log-file-null
Eclipse Error: 'An error has occurred. See the log file null' on Windows 10 with JRE 1.8.0_51 – How to Fix and Open Eclipse
Check: If Eclipse launches successfully, the issue was permissions. To avoid repeating this, reinstall Eclipse to a non-protected directory (e.g., C:\eclipse). Eclipse versions have strict Java requirements. For example: Eclipse 2023-09 requires Java 17 or later.
Discussions

nullpointerexception - How do I avoid checking for nulls in Java? - Stack Overflow
I use x != null to avoid NullPointerException. Is there an alternative? if (x != null) { // ... } More on stackoverflow.com
🌐 stackoverflow.com
December 5, 2020
java - Is Eclipse's null check analysis confused by JUnit's 'fail'? - Stack Overflow
Of course. The code is working fine, it's just the Eclipse null checker that is misbehaving. More on stackoverflow.com
🌐 stackoverflow.com
How to handle null values in Java (eclipse IDE) - Stack Overflow
I think those checks seem less complicated and more readable than this though. 2015-09-02T04:33:49.243Z+00:00 ... M. Shaw Over a year ago · @Zar Not when you have 10+ nested if null-checks. More on stackoverflow.com
🌐 stackoverflow.com
April 30, 2017
java - Why Eclipse null analysis ignore null-checking statement: if (someObject != null) {...}, when someObject is a field-scope variable? - Stack Overflow
I don't understand why Eclipse does not allow me to use field variable directly in null-checking statement if (someObject != null) but force me to create additional local variable someObject2. More on stackoverflow.com
🌐 stackoverflow.com
🌐
DZone
dzone.com › coding › frameworks › annotation-based null analysis in eclipse
Annotation-Based Null Analysis in Eclipse
January 13, 2017 - Null analysis: Check “Enable annotation-based null analysis” (a pop-up will do the next two for you) ... For the “Eclipse External Annotations,” a folder holding this information must be set. In my project, we use the location castle.util/eea. Project Properties ⇒ Java Build Path ⇒ Libraries ⇒
🌐
nipafx
nipafx.dev › inside-java-newscast-7
Handling null and Upgrading Past Java 8 - Inside Java Newscast #7 // nipafx
Object obj = null; // old-style type check if (obj instanceof String) // `instanceof` operator // rejects `null`, so this // branch isn't executed Object obj = null; // modern type pattern if (obj instanceof String s) // type patterns // reject `null`, so this // branch isn't executed · In switch, if JEP 406 gets released in Java 17 as it is proposed now, the case keyword is used and usually, something like case String s won't match null either (it only will if the variable is declared as String).
Published   July 1, 2021
Top answer
1 of 16
2877

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:

  1. Where null is a valid response in terms of the contract; and

  2. 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);
        }
    }
}
2 of 16
722

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.

🌐
Apache
sling.apache.org › documentation › development › null-analysis.html
Apache Sling :: Leveraging @NotNull/@Nullable annotations to prevent NullPointerExceptions
July 18, 2025 - This also affecs constants (static ... to '@Nonnull String'. The only known workaround is to disable the "Unchecked conversion from non-annotated type to @NonNull type" or to annotate also the field with @Nonnull....
Find elsewhere
🌐
Mkyong
mkyong.com › home › java › java – check if a string is empty or null
Java - Check if a String is empty or null - Mkyong.com
April 29, 2019 - In Java, we can use (str != null && !str.isEmpty()) to make sure the String is not empty or null.
🌐
Coderanch
coderanch.com › t › 593112 › java › check-null-entered-user-input
How to check for null value entered by user in input in eclipse (Beginning Java forum at Coderanch)
Try the following, then search around this forum or on the internet; the problem with string equality comes up quite a bit. Also not sure why you are setting lookfor to "\0"; Java doesn't require strings be null terminated. And Welcome to the ranch! Everything is theoretically impossible, until it is done. ~Robert A. Heinlein ... kar ja wrote: The code is written in Eclipse.
Top answer
1 of 6
4

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;
2 of 6
2

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

🌐
Reddit
reddit.com › r/java › plans for compile-time null pointer safety?
r/java on Reddit: Plans for Compile-time Null Pointer Safety?
July 16, 2022 -

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.

🌐
Eclipse
help.eclipse.org › latest › topic › org.eclipse.jdt.doc.user › tasks › task-using_null_annotations.htm
Using null annotations
In object-oriented programming the concept of Design by Contract needs to address one more dimension: sub-typing and overriding (in the sequel the term "override" will be used in the sense of the @Override annotation in Java 6: methods overriding or implementing another method from a super-type). A client invoking a method like this one: @NonNull String checkedString(@Nullable String in)
🌐
Baeldung
baeldung.com › home › java › avoid check for null statement in java
Avoid Check for Null Statement in Java | Baeldung
February 20, 2026 - Here, @NonNull makes it clear that the argument cannot be null. If the client code calls this method without checking the argument for null, FindBugs would generate a warning at compile time. Developers generally rely on IDEs for writing Java code.