3

This for loop is supposed to go through a String array and make the value hasEmpty true if the array contains either a null value or empty String. The following code gives me a NullPointerException.

String[] names = {null, "B", "C"};
    boolean hasEmpty = false;
    for(int i = 0; i<names.length; i++){
        if ((names[i].equals("")) || (names[i] == null))
            hasEmpty = true;
    }

But if I change the order of the OR statement in the if clause, the following code seems to work. Can someone tell me why this is so?

String[] names = {null, "B", "C"};
    boolean hasEmpty = false;
    for(int i = 0; i<names.length; i++){
        if ((names[i] == null) || (names[i].equals("")))
            hasEmpty = true;
    }
jxia-ux
  • 87
  • 8

7 Answers7

3

Because || is a short-circuit operator. As soon as it finds an operand that is true, from left to right, it doesn't even evaluates the other ones (because true or anything is always true).

The same goes with &&: if the first operand is false, it does evaluates the other ones, because false && anything is always false.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

|| is checking the first condition first , it faces a null ... calling equals on null throws NullPointerException

when you check for null first the first condition will evaluate to true so it will skip checking the 2nd one

Check this to understand the difference between single and double or/and as logical operators in java

Community
  • 1
  • 1
Abdelrahman Elkady
  • 2,518
  • 2
  • 21
  • 30
0

As it is expected.

If the first argument of an OR statement is true, it does not need to evaluate the other.

The same is true for an AND statement and a false value. If the first is false, no need to evaluate the second.

gibertoni
  • 1,368
  • 12
  • 21
0

Code in if statements are evaluated lazily, meaning that they can exit if they know that they're going to fail. The first one fails because you're calling null.equals("") which will throw an error. The second one succeeds because you're checking if names[i] is null and if so the loop is exited.

if ((names[i] == null ) ||
    (names[i].equals(""))) // Don't bother checking if names[i] is null


if ((names[i].equals("")) ||
    (names[i] == null)) // Check null only if names[i].equals("") is false

Inverting the || to an && might have it more sense:

if (names[i] != null && !names.equals(""))
Daniel Imms
  • 47,944
  • 19
  • 150
  • 166
0

equals() method needs the string not be null, if the value is null, it is not an object anymore and you actually call null.equals.(someOtherObject), then it throws NullPointerException as expected.

Haifeng Zhang
  • 30,077
  • 19
  • 81
  • 125
0
String[] names = {null, "B", "C"};

boolean hasEmpty = false;

for(int i = 0; i<names.length; i++){
       /* change here */
        if (("".equals(names[i])) || (names[i] == null))
            hasEmpty = true;
    }

Reason : You are trying to compare null value with empty string so in first code snippet you are getting NullPointerException. But in second code you changed that place of both conditions. The evaluation of OR condition is done as follow:


if first condition is fulfilled then only next part is checked.

means if (a || b)

if a is true then b will not be evaluated. but if a is false then b will be evaluated.

singhpradeep
  • 1,593
  • 1
  • 12
  • 11
0

Performance depends how many nulls and empty strings you have. Maybe that was the reason you choose check for empty string first because it happens more often. You can do this too but you should avoid null pointer exception too. There is simple trick to do this - rely on your code, not on data. If you simple change what is compared with what and use your constants then it will work fine. Your constants are not null since they do exist.

if (("".equals(names[i])) || (names[i] == null)){/* Handling empty or null strings */}

See the difference?

Izold Tytykalo
  • 719
  • 1
  • 5
  • 15