如何安全地处理Java的包装原语

时间:2015-02-13 14:02:24

标签: java nullpointerexception primitive autoboxing

我正在编写一个程序,需要处理具有许多包装数字变量的对象,如Long,Double,Integer等。如何安全地对这些变量执行数值运算而无需在任何地方放置

我希望这是几乎每个Java程序员必须迟早要处理的事情,所以我很惊讶没有数百个关于该主题的博客文章和SO问题。

我目前的解决方案是通过以下方法过滤所有数字:

private static safelyUnbox(Integer i) {
    return i == null ? 0 : i.intValue();
}
...
sumVariable += safelyUnbox(stupidObject.getNumberOfWhatever());

3 个答案:

答案 0 :(得分:5)

Java 8为检查null提供了一个很好的替代方案。如果Integer(例如)可能有也可能没有值,那么您可以将其声明为Optional<Integer>Optional类有很多有用的实用程序,用于返回默认值,抛出异常,检查值是否存在等。

声明Optional<Integer>的好处在于,您正在向读者清楚地表明“没有价值”。是一个合法的国家。任何维护代码的人别无选择,只能使用Optional方法来决定如果值存在或不存在会发生什么。

另一方面,如果参数是必需的,那么最简单的选择就是在使用之前断言它不是null。

在我可能不存在某个值的情况下使用Optional的最大好处是,您可以在假设null始终是错误的情况下开始依赖您的代码。

Optional甚至提供了一种将潜在的空变量转换为Optional的简洁方法(例如,如果它传递给您,并且您无法控制其在输入时的值你的代码)。它的工作原理如下:

Optional<Integer> optVal = Optional.ofNullable(val);

然后,您可以像使用任何其他Optional一样使用新变量。例如:

optVal.ifPresent(myList::add);

或者:

return optVal.orElse(27);

答案 1 :(得分:2)

你有一个非常具体的问题,并试图在不考虑它的情况下概括它。

  • 这可能是空值无效的前提条件。在您的情况下,您在评论中说明它不是。但如果是的话,你应该处理它而不是隐藏它。

  • “安全”值可能不同。您之所以选择0,是因为您要将这些数字相加,如果您乘以(或将其用作商数)会怎么样?这是您的safelyUnbox方法没有的知识。

避免概括一切。对于您的情况,最好的代码就像:

for(Integer integ : myCollection) {
  if (integ != null) {
    sum += integ;
  }
}

其他每种情况都有自己的,最合适的解决方案。将其与

进行比较
for(Integer integ : myCollection) {
  sum += safeUnboxThatDefaultsto0(integ);
}

for(Integer integ : myCollection) {
  sum += safeUnbox(integ, 0);
}

使用这种方法你赢了什么?

答案 2 :(得分:1)

您可以使用Google的番石榴图书馆Using and avoiding null

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5

Optional的最大优势不在于readability:优点是它的白痴证明。如果您希望程序完全编译,它会强制您主动考虑缺席情况,因为您必须主动解包可选并解决该情况。 Null让人很容易忘记事情。

假设这种情况:

String meterReading=getValueFromRemoteSite();
System.out.println(meterReading.toLowerCase()); //Chances for NPE

但使用可选方案是不同的

Optional meterReading = Optional.of(getValueFromRemoteSite(););
if( meterReading.isPresent() )
{
   System.out.println( meterReading.get() );
}