Я читал на многих веб-сайтах Необязательный должен использоваться только в качестве возвращаемого типа, а не в аргументах метода. Я изо всех сил пытаюсь найти логическую причину, почему. Например, у меня есть часть логики, которая имеет 2 дополнительных параметра. Поэтому я думаю, что имеет смысл написать сигнатуру моего метода следующим образом (решение 1):
public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
// my logic
}
Многие веб-страницы указывают, что Необязательно не следует использовать в качестве аргументов метода. Имея это в виду, я мог бы использовать следующую сигнатуру метода и добавить четкий комментарий Javadoc, чтобы указать, что аргументы могут быть нулевыми, надеясь, что будущие сопровождающие будут читать Javadoc и, следовательно, всегда выполнять нулевые проверки перед использованием аргументов (решение 2) :
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
В качестве альтернативы я мог бы заменить свой метод четырьмя открытыми методами, чтобы обеспечить более приятный интерфейс и сделать его более очевидным, p1 и p2 являются необязательными (решение 3):
public int calculateSomething() {
calculateSomething(null, null);
}
public int calculateSomething(String p1) {
calculateSomething(p1, null);
}
public int calculateSomething(BigDecimal p2) {
calculateSomething(null, p2);
}
public int calculateSomething(String p1, BigDecimal p2) {
// my logic
}
Теперь я пытаюсь написать код класса, который вызывает этот кусок логики для каждого подхода. Сначала я получаю два входных параметра из другого объекта, который возвращает Optional
s, а затем вызываю calculateSomething
. Поэтому, если используется решение 1, вызывающий код будет выглядеть так:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);
если используется решение 2, вызывающий код будет выглядеть так:
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));
если применяется решение 3, я мог бы использовать приведенный выше код или следующее (но это значительно больше кода):
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
if (p2.isPresent()) {
result = myObject.calculateSomething(p1, p2);
} else {
result = myObject.calculateSomething(p1);
}
} else {
if (p2.isPresent()) {
result = myObject.calculateSomething(p2);
} else {
result = myObject.calculateSomething();
}
}
Итак, мой вопрос: почему считается плохой практикой использовать Optional
s в качестве аргументов метода (см. Решение 1)? Это выглядит как наиболее читаемое решение для меня и делает наиболее очевидным, что параметры могут быть пустыми / нулевыми для будущих сопровождающих. (Я знаю, что разработчики Optional
предполагали, что он будет использоваться только в качестве возвращаемого типа, но я не могу найти логических причин не использовать его в этом сценарии).
null
?