Пояснение
null
- это значение, которое можно использовать только для объектов. A double
однако является примитивом, он не использует объектную систему. Вот почему вы не можете вернуть null
, если вы указали double
в качестве типа возвращаемого значения.
Итак, каковы ваши варианты?
Double
оболочка
Вместо этого вы можете использовать Double
, класс оболочки для double
, который использует объектную систему.
Поскольку Java обеспечивает автоматическое преобразование между double
и Double
при необходимости (автобокс), этоможет быть весьма удобным в использовании.
Обратите внимание, что использование Double
приводит к небольшим накладным расходам только к небольшому double
, и что люди регулярно забывают проверить null
при преобразовании Double
вdouble
. Т.е.
// 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>
(снова класс оболочки), есть также OptionalDouble
, которыйвнутренне использует double
(примитив). Вот код:
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();
}
Исключение
Последний вариант - просто выбросить исключение. Вы должны учитывать это всякий раз, когда пользователь делает что-то, что не предназначено, и против того, что вы считаете правильным использованием (укажите это в документации по вашим методам).
Я бы сказал, что в вашей конкретной ситуации это так,Невозможно вычислить mean
на null
. Это отличается от передачи в пустой массив, где я бы пошел для пустого 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
...
}
Результат
Собрав все это вместе, я бы сделал следующие два изменения:
- Бросок
NullPointerException
, если grades
равен null
, используя Objects#requireNonNull
- Вернуть пустое
OptionalDouble
, если grades
пусто
public OptionalDouble computeMean(double[] grades) {
Objects.requireNonNull(grades);
if (grades.length == 0) {
return OptionalDouble.empty();
}
...
return OptionalDouble.of(result);
}