【问题标题】:Missing value in JavaJava中的缺失值
【发布时间】:2012-05-30 04:51:51
【问题描述】:

在Java中可以使用什么语句来表示变量的缺失值。比如我想写一段代码:

if (a>=23)
 income = pay_rate;
else 
 income is missing;

【问题讨论】:

  • 有时 -1 用于表示缺失的int,在逻辑上不能为负数。
  • 投反对票的人愿意分享他们的理由吗? IMWTK。
  • @Andrew:使用 Java 5 自动装箱,真的不比使用包装对象方便。
  • @JonathanW 关于自动装箱的要点。
  • 初读时,这个问题看起来有点傻:这是一个非常经典的问题,我们中的大多数人以一种或另一种方式解决,大多数时候使用绝对不完美的解决方案。用更多的注意力思考它,我们可以看到答案一点也不简单,并且存在一个优雅的解决方案。我们对@missingfaktor 的回答有一个很好的解释。不值得任何反对,所以...

标签: java


【解决方案1】:

这个帖子里有很多不好的建议。首先让我解释一下为什么您应该采用一些建议的方法。

1.使用包装器类型和 null

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

Java 具有自动拆箱功能。如果您在 Java 必须自动拆箱的地方不小心使用了 income 怎么办?编译器无法捕获此错误,您的代码将在运行时崩溃。

其次,收入的“可空性”不是income 类型的一部分。因此,程序员每次使用时都要小心检查null。如果他忘记执行这个检查,编译器不会报错,但你会在运行时得到NullPointerExceptions。

2。使用标记值表示异常情况

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

这种方法具有null 方法的第二个缺点。更糟糕的是,在这种情况下,即使在错误的情况下,计算也会继续,而不是抛出异常,因为Integer.MAX_VALUE 是有效的int,这可能会导致灾难性的后果。


那么你应该如何处理呢?

使用以下数据类型:

  • 在其类型中表示“可空性”。
  • 不涉及上述两种方法中的条件检查。
  • 确保在编译时不会以非法状态访问数据。

Maybe(也称为Option)符合要求。 (@Bahribayli 已经提出了这个建议。我正在扩展它。)请参阅数据定义 here

这就是你在你的情况下使用它的方式:

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

有一个名为Functional Java 的库,即provides this abstraction。如果您对使用此数据类型有任何其他问题,我很乐意为您解答。

【讨论】:

  • 从中获得了一些新知识.. 谢谢!使用 Maybe 结构会对性能造成什么影响?
  • @Raze2dust,除非您在高性能密集型领域工作,否则无需担心。我主要是 Scala 开发人员(也是一种 JVM 语言),Maybe 恰好是处理“可选性”的方式。
  • +1。解释非常清楚,这导致开发人员(如我)对他们的代码更加严格。
【解决方案2】:

您正在寻找一个,而不是一个语句,该值是null。您不能将null 分配给primitive data types 的变量,例如intdouble,但您可以将它与它们的盒装 对应物一起使用——IntegerDouble 等等等。

当你这样做时,你应该在访问它们之前仔细检查你的 null 的值。否则,看似无辜的if (pay_rate &gt; 100) 可能会抛出空引用异常。

【讨论】:

  • 在java中,“内置”的术语是primitives
  • @Bohemian 感谢您的指正!晚上太晚了,我的头脑无法说出正确的词:)
【解决方案3】:

Option 类型论中的类型是一种指定变量类型的方法,该变量可能具有也可能没有有意义的值。某些语言支持 Option 类型,例如 Scala 的 scala.Option 类型。对于不支持该类型的语言,您可以使用包装类或原语的盒装对应物。

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

或者干脆

Integer income = null;
if( a >= 23)
  income = pay_rate;

【讨论】:

  • 添加如何在 Java 中做,你的答案脱颖而出 + 1
  • 我详细阐述了,但似乎访问者没有理解我提出的一般观点。
  • +1。我正在添加另一个更详细地阐述该技术的答案。
【解决方案4】:
Integer income = null;
if (a >= 23) {
  income = payRate; // underscores are generally considered bad convention in Java
}

【讨论】:

  • 我想找到所有观察的最低收入小时。如果最低incomeHr >=number,那么income_hr_min 应该是缺失的。
  • 但是“失踪”是什么意思? “缺失”如何影响下游计算?它应该表现得像 0,还是根本不应该执行某些计算?
  • 如果缺失,则进行其他计算。例如,如果 number_hrs_per_day>0 和 days_per_week
  • 对。这就是 null 的用途。
【解决方案5】:

您可以将收入设置为空。稍后,当您检查收入值时,如果它为空,则将其视为缺失

Integer income = a>=53?pay_rate:null;

【讨论】:

  • "?"问题是否要求条件,即“a>​​=b?”如果是,则返回“pay_rate”,否则返回“null”。如果条件为假,则执行“:”之后的代码。如果 cndition 为真,则执行 ":" 之前的代码。有关更多详细信息,请参阅此链接 - cafeaulait.org/course/week2/43.html
【解决方案6】:
Double income = null;
if (a>=23) {income = pay_rate; }

收入默认为null,所以如果未初始化

【讨论】:

  • 这是一个糟糕的建议。看我的回答。
【解决方案7】:

正如此处其他答案所述,您可以使用盒装类型。但我会建议为您的数据查找有效值并选择任何无效值作为缺失值。在您的具体收入情况下,不能为负数,因此您可以选择-1。

避免盒装类型的原因是性能。我不反对使用它们,但如果你可以在没有它们的情况下工作,那么就没有必要使用它们。

对于大多数 +ve 和 -ve 值都是有效值的情况,请使用Integer.MAX_VALUEInteger.MIN_VALUE 作为您的缺失值。您只会丢失所有可用值范围中的一个值。

注意:自动装箱(从原始类型隐式转换为装箱类型,反之亦然)是一个很好的功能,但可能会导致一些难以调试和发现的性能问题。

【讨论】:

  • 除非您进行非常密集的计算,否则自动装箱性能几乎可以肯定可以忽略不计。如果可以选择存在值,则应在不存在时使用 null。这比使用 -1 作为选项要清楚得多。保存用于数学、计数器等的原语。
  • @SOS 我无法理解您在评论中添加的一段代码想要什么。如果它与问题有关,请编辑您的问题。
  • 当我编译时:if((number_hrs_per_day>0) || (pay_rate= null) && (days_per_week 错误:无与伦比的类型:double 和
  • @JonathanW 你是对的。正如我所说,有些问题是显而易见的,例如Integer count = new Integer(10); for(int i=0; i&lt;count; i++);。但是这些很难找到,因为它们融合得很好……:)。同样使用 box 类型会增加导致 GC 调用的小对象创建。所以很多这些小事情很重要。但如果我正在使用一些已经为我提供 Boxed 类型数据的 ORM,我会很乐意使用它。
  • @SOS 您无法将double 数据类型与null 进行比较。要与null 进行比较,您必须使用盒装类型Double
【解决方案8】:

使用throws:

if (a>=23)
    income = pay_rate;
else 
    throw new IllegalArgumentException("income is missing");

【讨论】:

  • 除非听起来像缺少是一个有效的条件。您不应将异常用于正常或预期的控制流。
  • 我同意你的观点,只是想展示另一种方法:)
  • Excptions 应该在真正的例外情况下使用。
  • @Balaswamyvaddeman:我根据我的想法做了这个例子,如果 if-else 里面的方法和方法让说 getIncome() 有返回值 int 并且用户想要显示一个错误如果条件进入else,则发送消息。如果方法的返回值为void,则可以使用System.out.println("income is missing"); 显示错误消息,但如果返回值为int,则必须返回一个值,因此我抛出异常。只是想开箱即用,如果我做错了,请纠正我:-)
  • 例外情况是因为收入是int。如果缺失的收入并非例外,则不要将其建模为int,而是建模为Integer、自定义类型或Optional&lt;Integer&gt;,具体取决于上下文。
【解决方案9】:

你也可以试试这个,也许只是我喜欢的方式,但取决于你:p

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

不是默认设置为null,而是在检查a 是什么之后将其设置为null。另外,确保收入是IntegerDouble

【讨论】:

    【解决方案10】:

    你需要用null初始化变量

    Double income = null;
    if (a>=23) 
    {
       income = pay_rate; 
    }
    

    【讨论】:

      【解决方案11】:

      您可以通过以下方式进行:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-22
        • 2017-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        • 2020-10-19
        相关资源
        最近更新 更多