如何安全地处理 Java 的包装原语
How to safely handle Java's wrapped primitives
我正在编写一个程序,该程序需要处理包含许多包装数字变量的对象,例如 Long、Double、Integer 等。我如何才能安全地对这些对象执行数字运算而不必进行空值检查 无处不在?
我预计几乎每个 Java 程序员迟早都必须处理这个问题,所以我很惊讶没有数百篇博客文章和关于该主题的问题。
我目前的解决方案是通过这样的方法过滤所有数字:
private static safelyUnbox(Integer i) {
return i == null ? 0 : i.intValue();
}
...
sumVariable += safelyUnbox(stupidObject.getNumberOfWhatever());
Java 8 提供了一个很好的替代方法来检查 null
。如果一个整数(例如)可能有也可能没有值,那么您可以将其声明为 Optional<Integer>
。 Optional
class 有很多有用的实用程序,用于返回默认值、抛出异常、检查值是否存在等。
声明 Optional<Integer>
的好处是您向 reader 完全清楚 'no value' 是合法状态。维护您的代码的任何人都别无选择,只能使用 Optional
方法来决定如果值存在或不存在会发生什么。
另一方面,如果参数是强制性的,那么最简单的选择就是在使用它之前断言它不为空。
在我看来,只要值可能不存在,就使用 Optional
的巨大优势在于,您可以开始依赖代码,假设 null
始终是一个错误。
Optional
甚至提供了一种将可能为 null 的变量转换为 Optional
的巧妙方法(例如,如果它传递给您,而您在进入代码时无法控制它的值).它是这样工作的:
Optional<Integer> optVal = Optional.ofNullable(val);
然后您可以像使用任何其他变量一样使用新变量 Optional
。例如:
optVal.ifPresent(myList::add);
或:
return optVal.orElse(27);
您可以使用 Google 的 Guava 库 Using and avoiding null
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
Optional
的最大优势不在于 readability
:优势在于其防白痴性。如果您希望您的程序完全编译,它会迫使您积极考虑不存在的情况,因为您必须主动解包 Optional 并解决该情况。 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() );
}
您有一个非常具体的问题,并且试图在不考虑的情况下将其概括。
空值无效可能是一个先决条件。就您而言,您在评论中声明事实并非如此。但如果是,你应该处理它而不是隐藏它。
"safe" 值可能不同。您选择 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);
}
你用这个方法赢了什么?
我正在编写一个程序,该程序需要处理包含许多包装数字变量的对象,例如 Long、Double、Integer 等。我如何才能安全地对这些对象执行数字运算而不必进行空值检查 无处不在?
我预计几乎每个 Java 程序员迟早都必须处理这个问题,所以我很惊讶没有数百篇博客文章和关于该主题的问题。
我目前的解决方案是通过这样的方法过滤所有数字:
private static safelyUnbox(Integer i) {
return i == null ? 0 : i.intValue();
}
...
sumVariable += safelyUnbox(stupidObject.getNumberOfWhatever());
Java 8 提供了一个很好的替代方法来检查 null
。如果一个整数(例如)可能有也可能没有值,那么您可以将其声明为 Optional<Integer>
。 Optional
class 有很多有用的实用程序,用于返回默认值、抛出异常、检查值是否存在等。
声明 Optional<Integer>
的好处是您向 reader 完全清楚 'no value' 是合法状态。维护您的代码的任何人都别无选择,只能使用 Optional
方法来决定如果值存在或不存在会发生什么。
另一方面,如果参数是强制性的,那么最简单的选择就是在使用它之前断言它不为空。
在我看来,只要值可能不存在,就使用 Optional
的巨大优势在于,您可以开始依赖代码,假设 null
始终是一个错误。
Optional
甚至提供了一种将可能为 null 的变量转换为 Optional
的巧妙方法(例如,如果它传递给您,而您在进入代码时无法控制它的值).它是这样工作的:
Optional<Integer> optVal = Optional.ofNullable(val);
然后您可以像使用任何其他变量一样使用新变量 Optional
。例如:
optVal.ifPresent(myList::add);
或:
return optVal.orElse(27);
您可以使用 Google 的 Guava 库 Using and avoiding null
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
Optional
的最大优势不在于 readability
:优势在于其防白痴性。如果您希望您的程序完全编译,它会迫使您积极考虑不存在的情况,因为您必须主动解包 Optional 并解决该情况。 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() );
}
您有一个非常具体的问题,并且试图在不考虑的情况下将其概括。
空值无效可能是一个先决条件。就您而言,您在评论中声明事实并非如此。但如果是,你应该处理它而不是隐藏它。
"safe" 值可能不同。您选择
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);
}
你用这个方法赢了什么?