Java 检查是否已设置基元

Java 检查是否已设置基元,java,primitive,Java,Primitive,给定一个非常简单的类: class MyClass { int id; double value; MyClass(int id) { this.id = id; } void setValue(double v) { value = v; } boolean isValueUnassigned() { return value == 0; } } 要检查值是否尚未赋值,只需执

给定一个非常简单的类:

class MyClass {
    int id;
    double value;

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

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

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

要检查
是否尚未赋值,只需执行
返回值==0即可
由于默认情况下
double
0

那么,yes原语
double
默认设置为
0.0
。但是如果你只做
返回值==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的包装器类,即double。对于双数据类型,默认值为null。这样就不会有任何歧义。如果值为null,则不会为其分配任何值。

默认情况下,双精度值为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);
    }
}
class-MyClass{
私有int-id;
私人双重价值;
公共MyClass(内部id){
this.id=id;
}
公共无效设置值(双v){
值=v;
}
公共双getValue(){
//检查空指针并返回
如果(值==null)
返回;
返回值。doubleValue();;
}
公共布尔值isValueSet(){
返回值(值==null?false:true);
}
}
可以使用Double重新初始化Double,方法如下

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

您需要的是一个哨兵值,即表示这种情况的特殊值。通常有3种方法:


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

这种方法很好,速度也很快。但是,如果您(例如)开始引入数百个需要表示“尚未设置”的值,则无法很好地扩展


对象包装器 除实际值/实例外,对象变量还可以引用
null
。这可以用作指示特殊情况的哨兵

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

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

Double value = null;

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

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

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

这种方法非常普遍和有效。但它显然并不总是适用的,也不一定是最可读/可维护的方法

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;
}
double value=-1;
无效设置值(双值){
如果(值<0){
抛出新的IllegalArgumentException(“不允许使用负值”);
}
这个值=值;
}
布尔值isValueUnassigned(){
返回值==-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();
    }
}
class-MyClass{
int-id;
可选值;
MyClass(内部id){
this.id=id;
this.value=可选的.empty();
}
无效设置值(双v){
值=可选值(v);
}
双getValue(){
如果(isValueUnassigned){
抛出新的RuntimeException(“未分配值”);
}
返回值。get();
}
布尔值isValueUnassigned(){
返回值;
}
}

创建对象时会指定该值。您不需要使用方法检查值是否已赋值,因为答案总是肯定的。

如果我这么做是什么意思?是否要使用if语句检查值是否等于零?是。没关系。原语
double
初始化为
0
。但是,可以显式初始化变量。这被认为是良好的做法。如果我理解正确,您将检查双精度是否已更改。。。。问题是当0是一个有效值时,有人可以设置0。。。与检查方法相比,典型的方法是使用哨兵值(如附加的
布尔isSet
标志)或使用包装器对象(如
Double
)作为内部表示,它可以使用
null
作为哨兵值来指示这一点。而且,只有在应用程序允许的情况下,才能指定一个永远不能用作sentinel的值。例如
-1
年龄
字段的任何其他负值。但是用户可以故意将该值设置为
-1
。任何
double
值都可以用作有效值,但它们不能安全地用作哨兵。虽然这是一个选项,但它牺牲了相当多的内存和速度,用于一些也可以以不同方式解决的问题,例如使用一个简单的
布尔isSet
标志。@Zabuza不会添加额外的变量,因为这会使它变得混乱吗?只是想知道…视情况而定。在这种情况下,我会说它是好的(这是一个简单的类)。但总的来说,我同意。我只是想把它留作一个注释。注意,使用
可选的
作为字段是不好的。这违背了它的预期用途和设计。这是一个缺陷,不应该这样做。见和。可能存在一些罕见的边缘情况
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();
    }
}