我正在尝试在方法开始时测试空输入。如果发现为 true,我想返回 null,即使该方法通常会返回双精度。
我需要将方法类型保持为双倍
public double computeMean (double[] grades) {
if (grades == null) {
return null;
无法从空转换为双精度
解释
null
是一个只能用于对象的值。然而,double
是原语,它不使用对象系统。这就是为什么如果您将double
指定为返回类型,则无法返回null
。
那么,您有什么选择?
Double
包装器
您可以改用Double
,这是使用对象系统的double
包装类。
由于Java在需要时提供double
和Double
之间的自动转换(自动装箱(,因此使用起来非常方便。
请注意,使用Double
只会给一个小double
带来相当大的开销,并且人们在将Double
转换为double
时经常会忘记检查null
。
// foo() returns Double
double value = foo(); // Bad code, it could be null!
相反,用户必须记住检查结果值:
Double result = foo();
if (result == null) {
...
} else {
double value = result;
...
}
OptionalDouble
现代的,可能更好的选择是使用Optional
(为此,您至少需要Java 8(。
它被设计为在方法自然有时可能不返回结果时使用。例如,如果数组传入为空。这种情况是完全可以的,不应被视为错误。
这也解决了用户忘记检查结果的问题。Optional
迫使他们检查它,否则他们无法获得基础价值。
为了避免Optional<Double>
(再次包装类(的性能开销,还有内部使用double
(原语(的OptionalDouble
。这是代码:
public OptionalDouble computeMean(double[] grades) {
if (grades == null) {
return OptionalDouble.empty();
}
...
return OptionalDouble.of(result);
}
和用法:
OptionalDouble result = computeMean(...);
从那里,用户有几个选项(请参阅文档(,例如
double value = result.orElse(10.4);
// or
double value = result.orElseThrow();
// or
if (!result.isPresent()) {
...
} else {
double value = result.getAsDouble();
}
例外
最后一个选项是实际上只是抛出异常。每当用户执行非预期操作并且违反您认为正确的用法时,您应该考虑这一点(在您的方法文档中指出这一点(。
我实际上会说,在你的具体情况中,情况就是这样。不可能在null
上计算mean
。这与传入空数组不同,其中 I 将用于空Optional
。对于null
数组,我会抛出一个异常,以指示错误的用法。
这种情况的一个很好的例外是IllegalArgumentException
,这是代码:
public double computeMean(double[] grades) {
if (grades == null) {
throw IllegalArgumentException("Grades must not be null!");
}
...
}
正是这个用例的另一个惯用例外是抛出NullPointerException
.甚至还有一个紧凑的辅助方法可以在一行中完成所有这些操作:
public double computeMean(double[] grades) {
Objects.requireNonNull(grades); // Yes, thats it
...
}
结果
将所有这些放在一起,我将进行以下两个更改:
- 如果
grades
null
,则扔NullPointerException
,使用Objects#requireNonNull
- 如果
grades
为空,则返回空OptionalDouble
public OptionalDouble computeMean(double[] grades) {
Objects.requireNonNull(grades);
if (grades.length == 0) {
return OptionalDouble.empty();
}
...
return OptionalDouble.of(result);
}
你应该使用
Double
包装类(注意大写"d"(
如果您希望能够返回null
,则不double
基元类型作为返回类型。