11

What is the statement that can be used in Java to represent a missing value of a variable. for instance I want to write a code:

if (a>=23)
 income = pay_rate;
else 
 income is missing;
sarnold
  • 102,305
  • 22
  • 181
  • 238
SOS
  • 131
  • 1
  • 6
  • Sometimes -1 is used to represent a missing `int` that cannot logically be negative. – Andrew Thompson May 30 '12 at 04:57
  • 1
    Would the down-voter(s) care to share their reason(s)? IMWTK. – Andrew Thompson May 30 '12 at 04:58
  • 3
    @Andrew: with Java 5 autoboxing, it's really no more convenient than using wrapper objects. – Jonathan W May 30 '12 at 04:59
  • @JonathanW Good point about the auto-boxing. – Andrew Thompson May 30 '12 at 05:00
  • 3
    At first read, this question looks a bit silly : it's a really classic problem that most of us solve one way or another, most of the time with solutions that are absolutely not perfect. Thinking about it with more attention, we can see that the answer is not trivial at all, and that an elegant solution exists. And we have a nice explanation with @missingfaktor answer. Does not deserve any downvote, so... – Agemen Jun 05 '12 at 11:43

11 Answers11

14

There is a lot of bad advice in this thread. First let me address why you should not be going for some of the suggested approaches.

1. Using wrapper types and null

Integer income = null;
if (a >= 23) {
  income = payRate; 
}

Java has auto-unboxing. What if you somewhere accidentally use income in a place where Java had to auto-unbox it? The compiler cannot catch this error and your code will blow up at runtime.

Secondly, the "nullability" of income is not part of income's type. As a result, it's up to the programmer to be careful about checking it for null every time it is used. If he forgets to perform this check, compiler will not complain, but you will get NullPointerExceptions at runtime.

2. Using sentinel values to denote exceptional conditions

int income = Integer.MAX_VALUE;
if (a >= 23) {
  income = payRate;
}

This approach shares the second drawback of null approach. Even worse, in this case, instead of throwing an exception, computation will continue even in erroneous conditions, since Integer.MAX_VALUE is a valid int, leading to possible disastrous outcomes.


So how should you deal with this?

Use a data type that:

  • has "nullability" expressed in its type.
  • does not involve conditional checks such as in above two approaches.
  • ensures at compile time that the data is not being accessed in illegal state.

Maybe (also known as Option) fits the bill. (@Bahribayli already suggested this. I am expanding on it.) See the data definition here.

And this how you would use it in your case:

Maybe<Integer> income = Nothing.value();
if (a >= 23) {
  income = Just.of(payRate);
}

There is a library named Functional Java that provides this abstraction. If you have any further questions regarding the use of this data type, I will be happy to answer them.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • Gained some new knowledge from this.. thanks! What would be the performance hit of using the Maybe construct? – Hari Menon Jun 03 '12 at 12:35
  • 3
    @Raze2dust, unless you are working in a highly performance intensive domain, there is nothing to be worried about. I am primarily a Scala developer (also a JVM language), and there `Maybe` happens to be the way of handling "optionality". – missingfaktor Jun 03 '12 at 17:17
  • 1
    +1. The explanation is really clear, and that leads developers (like me) to be more strict with their codes. – Agemen Jun 05 '12 at 11:39
6

You are looking for a value, not for a statement, and that value is null. You cannot assign null to variables of primitive data types, such as int and double, but you can use it with their boxed counterparts -- Integer, Double, et cetera.

When you do that, you should be careful to check your values for null before accessing them. Otherwise, an innocent-looking if (pay_rate > 100) may throw a null reference exception.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
3

Option type in type theory is a way to specify type of a variable that may or may not have a meaningful value. Some languages support Option type like Scala's scala.Option type. For languages that don't support the type you can use wrapper classes or boxed counterparts for primitives.

public class Income {
  private int value;
  public Income(int value) {
    this.value = value;
  }
  public int getValue() {
     return value;
  }
  public void setValue(int value) {
    this.value = value;
  }
}

...
Income income = null;
if( a >= 23)
  income = new Income(pay_rate);

or simply

Integer income = null;
if( a >= 23)
  income = pay_rate;
Bahribayli
  • 346
  • 2
  • 11
2
Integer income = null;
if (a >= 23) {
  income = payRate; // underscores are generally considered bad convention in Java
}
Jonathan W
  • 3,759
  • 19
  • 20
  • i wanna find the minimum incomeHr for all observations. If the minimum incomeHr >=number then income_hr_min should be missing. – SOS May 30 '12 at 05:01
  • But what do you mean by "missing"? How does "missing" affect downstream calculations? Should it behave like a 0, or should certain calculations not be performed at all? – Jonathan W May 30 '12 at 05:03
  • if it's missing, then other calculations will be performed. for instance, If number_hrs_per_day>0 and days_per_week<0 or missing then income_hr = (//todo) – SOS May 30 '12 at 05:08
  • Right. That's what null is for. – Jonathan W May 30 '12 at 05:36
2

you can set income to null. Later, when you check value of income, if it is null, than treat it as missing

Integer income = a>=53?pay_rate:null;
Kshitij
  • 8,474
  • 2
  • 26
  • 34
  • "?" is the question asked for condition i.e. "is a>=b?" if yes then return "pay_rate" else return "null". The code after ":" is executed if the condiition is false. the code before ":" is executed if cindition is true. See this link for more detail - http://www.cafeaulait.org/course/week2/43.html – Kshitij May 30 '12 at 05:39
2
Double income = null;
if (a>=23) {income = pay_rate; }

income would be null by default so if uninitialized

jmj
  • 237,923
  • 42
  • 401
  • 438
2

As mentioned in other ans here, you can use a boxed type. But I ll recommend look for the valid values for your data and choose any invalid value for missing. In your specific case of income, which cannot be negative, so you can choose -1.

The reason to avoid boxed type is performance. I am not against using them but if you can work without them then there is no need to use them.

For the cases where most of +ve and -ve values are valid values, use eitherInteger.MAX_VALUE or Integer.MIN_VALUE as your missing value. You ll just loose one value of all the available value range.

NOTE: Auto-boxing (converting implicitly from primitive to boxed type and vice-versa) is a good feature but can lead to some performance issues which are difficult to debug and find.

havexz
  • 9,550
  • 2
  • 33
  • 29
  • Unless you are doing extremely intense calculations, autoboxing performance is almost certainly going to be negligible. If a value can optionally be present, you should use null when it isn't. That's far clearer than using the -1 as option. Save primitives for math, counters, etc. – Jonathan W May 30 '12 at 05:41
  • @SOS I cant understand wat you want with piece of code you put in the comment. If it is pertinent to the Question then edit your question. – havexz May 30 '12 at 05:43
  • when i compiled: if((number_hrs_per_day>0) || (pay_rate= null) && (days_per_week<0 <0 || days_per_week=null)), i got error mesg ==> error: incomparable types: double and – SOS May 30 '12 at 05:47
  • @JonathanW you are right. As i said some of the issues are in plain sight like `Integer count = new Integer(10); for(int i=0; i – havexz May 30 '12 at 05:47
  • @SOS you cannot compare `double` data-type with `null`. To compare against `null` you have to use boxed-type `Double`. – havexz May 30 '12 at 05:50
  • can i use this code to fine the Min incomeHrs: if(values[0] instanceof String){ if (values[0].equals("*")) return new Integer(Integer.MIN_VALUE); } List list = (List)values[0]; if(list.size() == 0){ return "*"; } else { Integer min = Collections.min(list); – SOS May 30 '12 at 06:27
2

Use throws:

if (a>=23)
    income = pay_rate;
else 
    throw new IllegalArgumentException("income is missing");
Crazenezz
  • 3,416
  • 6
  • 31
  • 59
  • 1
    Except that it sounds like missing is a valid condition. You shouldn't use exceptions for normal or expected control flows. – Jonathan W May 30 '12 at 05:42
  • I agree with you, just want to show another way to do that :) – Crazenezz May 30 '12 at 05:49
  • Excptions should be used in real exceptional conditions. – Balaswamy Vaddeman May 30 '12 at 06:38
  • @Balaswamyvaddeman: I made this example based on my Idea, what if the `if-else` inside in method and the method let say `getIncome()` has return value `int` and user want to show an error message if the condition get in `else`. If the return value of the method is `void` than you can display the error message using `System.out.println("income is missing");` but if the return value is `int` than you must return a value, so for that I throw the Exception. Just want to think out of the box, please correct me if I'm doing wrong :-) – Crazenezz May 30 '12 at 06:53
  • The exceptionality follows from the fact that income is an `int`. If a missing income is not exceptional, then don't model it as an `int`, but as an `Integer`, Custom type or `Optional` depending on the context. – Adriaan Koster Aug 22 '16 at 13:04
0

you could try this as well, maybe just the way I like to do it, but up to you :p

if(a >= 23){
    income = payRate;
} else{
    income = null;
}

rather than setting it to null by default, you set it to null after it checks what a is. also, make sure income is either an Integer or Double

Epicblood
  • 1,167
  • 2
  • 10
  • 29
0

You need to Initialize varible with null

Double income = null;
if (a>=23) 
{
   income = pay_rate; 
}
John Woo
  • 258,903
  • 69
  • 498
  • 492
0

You can do it following way:

public abstract class Nullable extends Number {

    protected final boolean isNA;


    protected Nullable(boolean isNA) {
        this.isNA = isNA;
    }

    public boolean isNA() {
        return isNA;
    }
}


public final class NullableInt extends Nullable {

    public static final NullableInt NA = new NullableInt(0, true);

    private final int value;

    public NullableInt(int value, boolean isNA) {
        super(isNA);
        this.value = value;
    }

    public static NullableInt of(int value) {
        return new NullableInt(value, false);
    }

    public int getValue() {
        if (!isNA) {
            return value;
        }
        throw new RuntimeException("Value is NA");
    }

    @Override
    public int intValue() {
        return getValue();
    }

    @Override
    public long longValue() {
        return getValue();
    }

    @Override
    public float floatValue() {
        return getValue();
    }

    @Override
    public double doubleValue() {
        return getValue();
    }
}

public class Test {

    public static void main(String[] args) {
        NullableInt[] nullableInts = new NullableInt[3];
        nullableInts[0] = NullableInt.of(1);
        nullableInts[1] = NullableInt.of(2);
        nullableInts[2] = NullableInt.NA;

        System.out.println(Arrays.toString(nullableInts));
    }
}
Eldar Agalarov
  • 4,849
  • 4
  • 30
  • 38