2

Given a very simple class:

class MyClass {
    int id;
    double value;

    MyClass(int id) {
        this.id = id;
    }

    void setValue(double v) {
        value = v;
    }

    boolean isValueUnassigned() {
        return value == 0;
    }
}

To check if value has not been assigned yet, is it OK if I just do return value == 0; since a double is 0 by default?

lucajyt
  • 19
  • 4
  • 1
    What do you mean by "if I just do"? Do you want to use an if statement to check if the value is equal to zero? – Mark Santos Nov 16 '19 at 09:12
  • yes. it is OK. primitive `double` is initialized to `0`. However, you can explicitly initialize the variable. it is considered good practice. – Sharon Ben Asher Nov 16 '19 at 09:15
  • 1
    if i understand it right you will check if the double has changed? .... The problem is when 0 is a valid value someone could set 0 ... than your check method behave wrong – pL4Gu33 Nov 16 '19 at 09:16
  • 2
    The typical approaches are either to use a sentinel value, like an additional `boolean isSet` flag or to use a wrapper object like `Double` for the internal representation which can use `null` as sentinel value to indicate this. And, only if your application allows it, you can designate a value that can never be used as sentinel. For example `-1` or any other negative value for an `age` field. – Zabuzard Nov 16 '19 at 09:21

8 Answers8

5

You should go for wrapper class for double which is Double. For Double data type default value would be null. So that there would not be any ambiguity. If value is null, then it's not assigned any value.

  • While this is an option, it sacrificaes quite some memory and speed for something that can also be solved differently, e.g. with a simple `boolean isSet` flag. – Zabuzard Nov 16 '19 at 09:24
  • @Zabuza Won't adding an extra variable for this makes it confusing? Just wondering... – utkarsh31 Nov 16 '19 at 09:31
  • Depends. In this case I would say it is okay (it is a simple class). But in general, I do agree. I just wanted to leave it as a note. – Zabuzard Nov 16 '19 at 09:34
4

Well, yes primitive double is set to 0.0 by default. But if you simply do return value == 0; you can't be sure if someone called setValue(0) before, but it is a valid assignment too. If you want to be 100% sure if someone called the setValue() I would suggest something like this:

class MyClass {
    private int id;
    private double value;
    private boolean valueSet; // is false by default 

    public MyClass(int id) {
        this.id = id;
    }

    public void setValue(double v) {
        value = v;
        valueSet = true;
    }

    public boolean isValueSet() {
        return valueSet;
    }
}
bambula
  • 365
  • 1
  • 12
0

Adding to what @Harshal has already said. Code for something like that would look like:

class MyClass {
    private int id;
    private Double value;

    public MyClass(int id) {
        this.id = id;
    }

    public void setValue(double v) {
        value = v;
    }

    public double getValue() {
        //Check for null pointer and return 
        if(value == null)
            return <whatever you want>;

        return value.doubleValue();;
    }

    public boolean isValueSet() {
        return (value == null ? false : true);
    }
}
utkarsh31
  • 1,439
  • 2
  • 13
  • 20
0

You can use Double to reinitialize the double using following

class MyClass {
    int id;
    Double value;

MyClass(int id) {
    this.id = id;
}

void setValue(Double v) {
    value = v;
}

boolean isValueUnassigned() {

   return value == null ? false : true;
}
}
Rajeev Ranjan
  • 272
  • 2
  • 11
  • 20
0

Explanation

The main issue here is that, whatever double value you choose, e.g. 0 or -1, it could actually be a valid value set by the user. In which case your application would falsely return that it was not set yet, while it was.

What you need is called a sentinel value, i.e. a special value that indicates this case. Typically there are 3 approaches:


Flag

Introduce a simple boolean flag boolean isSet which you initialize to false and set to true once it was set.

This approach is good and really fast. But does not scale well if you, for example, start to introduce hundreds of such values for which you need to represent "not set yet".

double value;
boolean isValueSet = false;

void setValue(double value) {
    this.value = value;
    isValueSet = true;
}

boolean isValueUnassigned() {
    return !isValueSet;
}

Object wrapper

Object variables can, additionally to their actual values/instances also refer to null. This can be used as sentinel to indicate the special case.

So you could go for having the value internally represented as Double instead of double, starting with null.

The disadvantage is that an object introduces quite some memory and performance overhead compared to a simple primitive. In this case it does not really matter but if you scale this up to a couple of thousands of them, you would definitely start to feel the impact.

Double value = null;

void setValue(double value) {
    this.value = value; // auto-boxing
}

boolean isValueUnassigned() {
    return value == null;
}

Sentinel value

If you application naturally allows that some values can never be used, you can use them as sentinel to indicate the case. A common example would be an age field for which you would not allow the user to set it to negative values. Then you can use, for example -1 to indicate it.

This approach is quite common and efficient. But it obviously is not always applicable and it is also not necessarily the most readable/maintainable approach.

double value = -1;

void setValue(double value) {
    if (value < 0) {
        throw new IllegalArgumentException("Negative values are not allowed");
    }
    this.value = value;
}

boolean isValueUnassigned() {
    return value == -1;
}
Zabuzard
  • 25,064
  • 8
  • 58
  • 82
0

The value is assigned when the object is created. You don't need a method to check if the value has been assigned because the answer is always yes.

LowKeyEnergy
  • 652
  • 4
  • 11
-1

Found the cleanest and clearest way to express it:

class MyClass {
    int id;
    Optional<Double> value;

    MyClass(int id) {
        this.id = id;
        this.value = Optional.empty();
    }

    void setValue(double v) {
        value = Optional.of(v);
    }

    double getValue() {
        if (isValueUnassigned) {
            throw new RuntimeException("Value has not been assigned");
        }
        return value.get();
    }

    boolean isValueUnassigned() {
        return value.isEmpty();
    }
}
lucajyt
  • 19
  • 4
  • Note that using `Optional` as field is **bad**. It is against its intended use and design. This is a flaw and should not be done. See [Uses for Optional](https://stackoverflow.com/questions/23454952/uses-for-optional) and [Is it a good practice to use Optional as an attribute in a class?](https://stackoverflow.com/questions/29033518/is-it-a-good-practice-to-use-optional-as-an-attribute-in-a-class). There are some rare edge cases where it might be _okay_, this is not one of them. Head over to the linked threads for in-depth explanations. – Zabuzard Nov 19 '19 at 13:36
-3

a double value is 0 by default , but you can pass -1 to it .

double value = -1;

for check :

 if (value!= -1) {
    // To Do
 }
  • 2
    But an user could set the value to `-1` on purpose. Any `double` value could be used as valid value, they can not be safely used as sentinel. – Zabuzard Nov 16 '19 at 09:22