1

As far as I know Java SE 8 has java.util.Optional<T> class that protects the code against unintended null pointer exceptions. But for some reasons I have to use Java 7.

Take a look at my example:

String version = device.getController().version;

What is the best practice to check device and getController() for null?

Option 1:

String version = "unknown";
if(device!=null){
  if(device.getController()!=null) 
    version = device.getController().version;
}

Option 2:

String version = "unknown";
if(device!=null && device.getController()!=null){
  version = device.getController().version;
}

Option 1 is a bit cumbersome, but obviously it will work correctly. The second options is questionable, because the fact that we do not know which part of condition will be checked first and how Java actually do it. There is a point to suggest that Java checks 2 parts of conditions before returning the result. Obviously, the second part will return NullPointerException in case device is null. So, what is the best way to check nested objects in Java 7 and earlier?

Nolesh
  • 6,848
  • 12
  • 75
  • 112
  • You might also cache the result of `device.getController()`. – Johannes Kuhn Jun 15 '18 at 14:46
  • Java ands are fail-fast. If you do something like `if(false and methodThatCrashesTheApp())` it will not crash the app. – Compass Jun 15 '18 at 14:46
  • 6
    *we do not know which part of condition will be checked first*: yes, we do. The first one will always be checked before the second one. And the second one will never be evaluated if the first one is false. That's part of the Java Language Specifications. – JB Nizet Jun 15 '18 at 14:46
  • 1
    Canonical answer https://stackoverflow.com/questions/1795808/and-and-or-in-if-statements – Compass Jun 15 '18 at 14:47
  • 1
    Both code snippets do the exact same thing. "The second options is questionable, because the fact that we do not know which part of condition will be checked first and how Java actually do it." is not correct - the statements are always evaluated left to right. https://stackoverflow.com/questions/17923872/condition-evaluation-process-in-java – Nate Jun 15 '18 at 14:48
  • Is there null conditional operator as in C#? – information_interchange Jun 15 '18 at 14:49
  • Also, if you want to use optional without upgrading to JDK 8+ (Why?!? Even JDK 8 is EOLed now...) you can use [Guava](https://google.github.io/guava/releases/19.0/api/docs/com/google/common/base/Optional.html) – Nate Jun 15 '18 at 14:50
  • There is no null conditional operator (otherwise known as elvis operator) in Java, as in C#. The closest is `device==null||device.getController()==null?"unknown":device.getController().version;` – Mark Jeronimus Jun 15 '18 at 15:23

4 Answers4

3

The second options is questionable, because the fact that we do not know which part of condition will be checked first and how Java actually do it.

That is not a fact. It is an anti-fact.

An <expr1> && <expr2> expression will be evaluated as follows:

  1. <expr1> is evaluated first.
  2. If the result of <expr1> is false, then <expr2> is NOT evaluated. The value of the expression is false.
  3. If the result of <expr1> is true, then <expr2> is evaluated, and that becomes the value of the expression.

The above is a simplified version. The actual specification is in JLS 15.23.

But my point is that there is absolutely zero uncertainty about how an && expression is evaluated. It has been clear and unambiguous for every version of Java from Java 1.0 onward ... if you read the official specifications and / or official tutorials.

Your options 1 and 2 are functionally identical.

The "best" way is a matter of opinion, but I prefer option 2 because it is more concise and equally readable. (Just my opinion ... obviously.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

Option 1 and Option 2 are functionally the same

You can use a ternary operator since you mentioned that option 1 is a bit "cumbersome"

String version = (device != null && device.getController() != null) ? device.getController().version : "unknown";
k2zinger
  • 382
  • 7
  • 15
0

Your 2nd option is perfectly valid. Java evaluates the conditions from left to right. That means that it will first evaluate device!=null and then device.getController()!=null.

If the left side of the AND condition (device != null) is found to be false, java will not evaluate the right side. The right side will only be evaluated for device!=null.

vatbub
  • 2,713
  • 18
  • 41
0

There is no problem with option 2, firstly it will check

device != null

if this is false i.e device is null, there will be no check for

device.getController()!=null

because False && (True/False) is False

I will suggest you to use try and catch.

String version = null;
try {
       version = device.getController().version;
     } catch (NullPointerException ex) {
         //log the error here
     }
singh30
  • 1,335
  • 17
  • 22