【问题标题】:Check if primitive has been set检查是否已设置原语
【发布时间】:2020-03-12 07:44:33
【问题描述】:

给定一个非常简单的类:

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;可以吗,因为double默认是0

【问题讨论】:

  • “如果我只是这样做”是什么意思?是否要使用 if 语句来检查值是否等于 0?
  • 是的。没关系。原始double 被初始化为0。但是,您可以显式初始化变量。这被认为是好的做法。
  • 如果我理解正确,你会检查双倍是否改变了? ....问题是当 0 是一个有效值时有人可以设置 0 ...而不是您的检查方法行为错误
  • 典型的方法是使用一个标记值,比如一个额外的boolean isSet 标志,或者使用一个像Double 这样的包装对象作为内部表示,它可以使用null 作为标记值来指出这一点。而且,只有在您的应用程序允许的情况下,您才能指定一个永远不能用作哨兵的值。例如-1age 字段的任何其他负值。

标签: java primitive


【解决方案1】:

你应该为 double 选择包装类,即 Double。对于 Double 数据类型,默认值为 null。这样就不会有歧义了。如果 value 为 null,则不为其分配任何值。

【讨论】:

  • 虽然这是一个选项,但它牺牲了相当多的内存和速度来换取一些也可以以不同方式解决的问题,例如带有一个简单的boolean isSet 标志。
  • @Zabuza 不会为此添加一个额外的变量会让人感到困惑吗?只是想知道......
  • 视情况而定。在这种情况下,我会说没关系(这是一个简单的类)。但总的来说,我同意。我只是想留个便条。
【解决方案2】:

嗯,是的,原始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;
    }
}

【讨论】:

    【解决方案3】:

    补充@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);
        }
    }
    

    【讨论】:

      【解决方案4】:

      您可以使用 Double 使用以下方法重新初始化双精度

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

      【讨论】:

        【解决方案5】:

        说明

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

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


        标志

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

        这种方法很好而且非常快。但是,如果您开始引入数百个需要表示“尚未设置”的此类值,则无法很好地扩展。

        double value;
        boolean isValueSet = false;
        
        void setValue(double value) {
            this.value = value;
            isValueSet = true;
        }
        
        boolean isValueUnassigned() {
            return !isValueSet;
        }
        

        对象包装

        除了它们的实际值/实例之外,对象变量还可以引用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;
        }
        

        【讨论】:

          【解决方案6】:

          在创建对象时分配值。您不需要检查值是否已分配的方法,因为答案始终是肯定的。

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

            【解决方案8】:

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

            double value = -1;

            检查:

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

            【讨论】:

            • 但是用户可以故意将值设置为-1。任何double 值都可以用作有效值,它们不能安全地用作哨兵。
            猜你喜欢
            • 2011-05-29
            • 1970-01-01
            • 2014-06-15
            • 1970-01-01
            • 2011-07-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多