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.
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
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;
}
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
I'm 4 y experienced Java dev but still it's unclear how and when to check nullity sometimes and it happened today. Let's say there is a table called students and it has column called `last_name` which is not null.
create table students (
last_name varchar(255) not null
)You have written validation code to ensure all required column is appeared while inserting new record and there is a method that needs last_name of students. The parameter of this method may or may not come from DB directly(It could be mapped as DTO). In this case do you check nullity of `last_name` even though you wrote validation code? Or just skip the null check since it has not null constraint?
I know this depends on where and how this method is used and i skipped the null check because i think this method is not going to be used as general purpose method only in one class scope.
I'm coming back to Java after almost 10 years away programming largely in Haskell. I'm wondering how folks are checking their null-safety. Do folks use CheckerFramework, JSpecify, NullAway, or what?
Your solution is very smart. The problem I see is the fact that you don't know why you got a null? Was it because the house had no rooms? Was it becuase the town had no houses? Was it because the country had no towns? Was it because there was a null in the 0 position of the collection because of an error even when there are houses in positions 1 and greater?
If you make extensibe use of the NonPE class, you will have serious debugging problems. I think it is better to know where exactly the chain is broken than to silently get a null that could be hiding a deeper error.
Also this violates the Law of Demeter: country.getTown().getHouses().get(0).getLivingRoom(). More often than not, violating some good principle makes you have to implement unorthodox solutions to solve the problem caused by violating such principle.
My recommendation is that you use it with caution and try solve the design flaw that makes you have to incur in the train wreck antipattern (so you don't have to use NonPE everywhere). Otherwise you may have bugs that will be hard to detect.
The idea is fine, really good in fact. Since Java 8 the Optional types exist, a detailed explanation can be found at Java Optional type. A example with what you posted is
Optional.ofNullable(country)
.map(Country::getTown)
.map(Town::Houses);
And further on.
public static <T> T ifNull(T toCheck, T ifNull) {
if (toCheck == null) {
return ifNull;
}
return toCheck;
}
All in all to avoid statement
if (object != null) {
....
}
since java 7 you can use
Objectsmethods:Objects.isNull(object)
Objects.nonNull(object)
Objects.requireNonNull(object)
Objects.equals(object1, object2)
since java 8 you can use Optional class (when to use)
object.ifPresent(obj -> ...); java 8
object.ifPresentOrElse(obj -> ..., () -> ...); java 9
rely on method contract (JSR 305) and use Find Bugs. Mark your code with annotations
@javax.annotation.Nullableand@javax.annotation.Nonnnul. Also Preconditions are available.Preconditions.checkNotNull(object);
In special cases (for example for Strings and Collections) you can use apache-commons (or Google guava) utility methods:
public static boolean isEmpty(CharSequence cs) //apache CollectionUtils
public static boolean isEmpty(Collection coll) //apache StringUtils
public static boolean isEmpty(Map map) //apache MapUtils
public static boolean isNullOrEmpty(@Nullable String string) //Guava Strings
- When you need to assign default value when null use apache commons lang
public static Object defaultIfNull(Object object, Object defaultValue)
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.
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.