检查原语是否已设置

Check if primitive has been set

给出一个很简单的class:

class MyClass {
    int id;
    double value;

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

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

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

要检查 value 是否还没有被分配,如果我只做 return value == 0; 可以吗,因为默认情况下 double0

嗯,是的,原始 double 默认设置为 0.0。但是如果你只是做 return value == 0; 你不能确定之前是否有人叫过 setValue(0) ,但这也是一个有效的分配。如果你想 100% 确定是否有人打电话给 setValue() 我会建议这样的事情:

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;
    }
}

你应该为 double 使用包装器 class,它是 Double。对于 Double 数据类型,默认值为空。这样就不会有歧义了。如果值为 null,则不会为其分配任何值。

double 值默认为 0,但您可以将 -1 传递给它。

double value = -1;

检查:

 if (value!= -1) {
    // To Do
 }

补充@Harshal 已经说过的话。类似的代码如下所示:

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);
    }
}

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;
}
}

说明

这里的主要问题是,无论您选择什么 double 值,例如0-1,它实际上可以是用户设置的有效值。在这种情况下,您的应用程序会错误地 return 它尚未设置,而实际上它已设置。

您需要的是 标记值,即指示这种情况的特殊值。通常有 3 种方法:


旗帜

引入一个简单的布尔标志 boolean isSet,您将其初始化为 false 并在设置后设置为 true

这种方法很好而且非常快。但是,如果您开始引入数百个需要表示 "not set yet".

的此类值,则无法很好地扩展
double value;
boolean isValueSet = false;

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

boolean isValueUnassigned() {
    return !isValueSet;
}

对象包装器

对象变量除了它们实际的 values/instances 之外还可以引用 null。这可以作为哨兵来指示特殊情况。

因此您可以将值在内部表示为 Double 而不是 double,从 null.

开始

缺点是与简单的原语相比,对象会引入相当多的内存和性能开销。在这种情况下,这并不重要,但如果将其扩展到数千个,您肯定会开始感受到影响。

Double value = null;

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

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

哨兵值

如果您的应用程序自然允许某些值永远不能使用,您可以将它们用作标记来指示这种情况。一个常见的例子是 age 字段,您不允许用户将其设置为负值。那么就可以使用,比如-1来表示。

这种方法很常见也很有效。但它显然并不总是适用,也不一定是最readable/maintainable的方法。

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;
}

找到最简洁明了的表达方式:

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();
    }
}

创建对象时赋值。您不需要一种方法来检查值是否已分配,因为答案总是肯定的。