Допустим, у меня есть класс:
public class RectangularPrism{
public Integer width;
public Integer height;
public Integer depth;
//setters and getters
}
Я использую его для вычисления суммы объема всех призм. У меня есть два метода для расчета этого. Какая из них лучше?
В этом случае используется условный оператор.
public Integer volumeSum(List<RectangularPrism> prismList){
Integer sum = 0;
for(RectangularPrism prism: prismList){
Integer width = prism.getWidth() == null ? 0 : prism.getWidth();
Integer height = prism.getHeight() == null ? 0 : prism.getHeight();
Integer depth = prism.getDepth() == null ? 0 : prism.getDepth();
sum += width * height * depth;
}
return sum;
}
Этот блок try try catch
public Integer volumeSum(List<RectangularPrism> prismList){
Integer sum;
for(RectangularPrism prism: prismList){
try {
Integer width = prism.getWidth();
Integer height = prism.getHeight();
Integer depth = prism.getDepth();
sum += width * height * depth;
}catch( NullPointerException e){}
}
return sum;
}
Какой был бы лучше Если бы у моего класса было 100 или более полей, которые определяли бы результат?
Можно ли использовать try catch для обработки нулевых значений?
Это плохая идея на каждом уровне.
try-catch
на самом деле медленнее (если действительно есть исключение)try-catch
бросает законный NPE, вы не можете сказать, что произошло. (Представьте себе случай, когда сама prism
равна нулю).?:
Для проверки нулей - это хорошо установленный шаблон, который все узнают.catch
блок не является большой нет-нет, да и, пожалуй, самый надежный метод генерации ошибок, которые будут принимать возрастов, чтобы отследить.null
значение null
будет означать, что остальная часть блока try
будет пропущена. Конечно, sum
будет по-прежнему правильной, но это просто совпадение. Если вы действительно хотите повысить производительность, не используйте Integer
и другие классы упаковки для простых вычислений, вместо этого используйте соответствующий примитив (int
в этом случае). Дополнительный бонус этого заключается в том, что вам не придется больше беспокоиться о null
потому что примитивные значения никогда не могут быть null
.
Серьезно, не надо. Каждый раз, когда вы это делаете, милый маленький котенок умирает.
try...catch
здесь - обработать нулевую prism
… кроме этого, я полностью согласен (но я не против, если несколько котят умрут: P)
Вы никогда не должны использовать try-catch
для управления потоком управления вашей программой.
Всегда используйте установленные методы, в этом случае проверяйте значение null, как и в первом примере кода.
Я знаю, что это не ответит на вопрос (можно try.. catch
будет использоваться для оптимизации кода), но я думаю, что вы редко должны беспокоиться о null
значениях: вы должны применять (width
, height
, depth
), чтобы они были не null
если они внутреннее свойство вашего объекта.
Я имею в виду, вы строите RectangularPrism
: width
, height
и depth
определяют этот объект. Вы не можете иметь null
потому что иначе это будет не прямоугольная призма.
В этом случае я бы предпочел:
public class RectangularPrism {
private final Integer width;
private final Integer height;
private final Integer depth;
public RectangularPrism(Integer width, Integer height, Integer depth) {
this.width = Objects.requireNonNull(width, "width");
this.height = Objects.requireNonNull(height, "height");
this.depth = Objects.requireNonNull(depth, "depth");
}
// getters
}
Или с сеттером:
public class RectangularPrism {
public Integer width;
public Integer height;
public Integer depth;
public void setWidth(Integer width) {
this.width = Objects.requireNonNull(width, "width");
}
}
Вам не нужно обрабатывать null
потому что JVM будет генерировать NullPointerException
, но только потому, что объект не был полностью/правильно инициализирован, а не потому, что вы не обрабатывали null
значение, которого не должно быть. Это нормальное поведение, например, бросание IllegalStateException
потому что объект находится в состоянии, которого он не должен быть (здесь: потому что у вас есть null
значения).
И чтобы быть полным, у вас была бы лучшая реализация, если бы объемное вычисление было операцией над RectangularPrism
а не внешней операцией.
Этот путь был бы более правильным:
public class RectangularPrism {
private final Integer width;
private final Integer height;
private final Integer depth;
public RectangularPrism(Integer width, Integer height, Integer depth) {
this.width = Objects.requireNonNull(width, "width");
this.height = Objects.requireNonNull(height, "height");
this.depth = Objects.requireNonNull(depth, "depth");
}
public Integer computeVolume() {
return width * height * depth; // can't be null.
}
}
Тогда (я использовал int
там, потому что есть сумма, я не буду комментировать использование примитивного класса оболочки):
public Integer volumeSum(List<RectangularPrism> prismList) {
int initial = 0;
for (RectangularPrism p : prismList)
initial += p.computeVolume();
return initial;
}
И последнее, но не менее важное: обработка исключений медленнее, но обработка исключений в цикле медленнее.
int
если вы рассматриваетеnull
как 0.