-2

Say

class Person{
    Integer height;
    integer weight;
}

is it valid to check like this?

Person p = new Person();
if (p.height !=null && p.height >= 1 && p.weight >=1 ){}
Jems
  • 11,560
  • 1
  • 29
  • 35
Ember user
  • 15
  • 2
  • 1
    Does this answer your question? [Java logical operator short-circuiting](https://stackoverflow.com/questions/8759868/java-logical-operator-short-circuiting) – maloomeister Jan 27 '21 at 10:49
  • Looks ok to me, be sure that height and weight get initialised, otherwise you will get a null pointer exception – jr593 Jan 27 '21 at 10:49
  • TL;DR: Yes, this is fine, because once the left hand side of the `&&` is found to be false, the right hand side will not be evaluated. (You only cover height btw, you might need to add a check for weight aswell) – maloomeister Jan 27 '21 at 10:50
  • Yes, because of [short circuiting](https://stackoverflow.com/questions/8759868/java-logical-operator-short-circuiting) of the `&&` and `||` operators doing `if( x != null && x.someMethod())` is valid and safe because if the first part `x != null` evaluates to false (x is null) then the rest of that statement is no longer evaluated because `false && ....` is always false no matter what follows. In your example above however you do not check if `p.weight` isn't null as well. So you might get a `NullPointerException` when the code reaches `p.weight >=1` and weight is `null` – OH GOD SPIDERS Jan 27 '21 at 10:50

3 Answers3

2

It's fine, but note that this will still crash with a NullPointerException if p.weight is null. If you want clean code, consider this question:

What does height is null actually mean? Does it mean:

  • It is semantically equivalent to 0. (Then, why have it? Make your fields int, and set them properly).
  • It is unknown.
  • It is unset; this is a person who does not want their height publicized.

In particular, given that you are checking for >= 1, apparently you can have a null height, but also a negative height. What is the semantic difference between these two? If there is no difference, why are you allowing a cavalcade of different internal values that nevertheless all boil down to representing the same state? You're signing up for a bevy of checks everytime you interact with these variables, and a combinatorial explosion to test all this. Don't do it this way - create a single value to represent 'invalid' or 'unknown' or 'intentionally omitted' or whatever it is that you need to convey.

Usually it leads to better code if you [A] eliminate invalid state as early as possible, which in particular means that you do not need to check for invalid state (here, 0 and negative numbers appear to be intended as invalid) every time you use these variables, and [B] use a sentinel value and not null to indicate a unique state such as 'unset' or 'intentionally not shared'.

In other words:

  • Make height and weight private
  • Their setters will refuse to set (and throw IllegalArgumentException instead) if trying to set 0 or negative height or weight.
  • The fields are of type int
  • Constants exist for the various alternate states.
public class Person {
    private static final int UNKNOWN = -1;
    private static final int INTENTIONALLY_OMITTED = -2;
    private int height, weight;

    public Person() {
      this.height = UNKNOWN;
      this.weight = UNKNOWN;
    }

    public void setHeight(int height) {
      if (height < 1) throw new IllegalArgumentException("Non-positive height");
      this.height = height;
    }

    public void setHeightOmitted() {
      this.height = INTENTIONALLY_OMITTED;
    }
}

and so on. Now you can write code that is inherently readable; null is nebulous (you'd have to document what it means. Does it mean unset, or invalid, or intentionally omitted? What?), if (height == INTENTIONALLY_OMITTED) documents itself, that's a good thing.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • If it is important to note the associativity and short-circuiting behaviour of `&&` operator, then please do for the shake of completeness. +1. I found about the short-circuiting behaviour into the docs [here](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html). – gthanop Jan 27 '21 at 11:02
0

Yes this is valid because Integer is the class representing int.

This is the reason why Integer can hold a null value. Comparison at p.height and p.weight is also valid.

dubka
  • 11
  • 2
0

Yes, because in case of && operation if first condition is true, then after second condition will be checked. If p.height is null then, First condition is false so, no other conditions will be checked.

You also have to add null check for p.width also.

Abrar Malekji
  • 111
  • 1
  • 4