Можно ли использовать catch для оптимизации кода?

1

Допустим, у меня есть класс:

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 для обработки нулевых значений?

  • 0
    Вы должны использовать try catch, потому что тогда вы не проверяете каждый случай, если один из них не удался, тогда он пропустит остальные.
  • 0
    Может быть, вам следует просто использовать int если вы рассматриваете null как 0.
Показать ещё 2 комментария
Теги:
try-catch
nullpointerexception

3 ответа

13
Лучший ответ

Это плохая идея на каждом уровне.

  1. try-catch на самом деле медленнее (если действительно есть исключение)
  2. Вы используете исключения в не исключительном случае (т.е. нормальный поток управления), что является концептуально неправильным.
  3. Если что-либо еще в блоке try-catch бросает законный NPE, вы не можете сказать, что произошло. (Представьте себе случай, когда сама prism равна нулю).
  4. Из всего кода очень сложно понять, каковы были ваши намерения. Использование оператора ?: Для проверки нулей - это хорошо установленный шаблон, который все узнают.
  5. Пустой catch блок не является большой нет-нет, да и, пожалуй, самый надежный метод генерации ошибок, которые будут принимать возрастов, чтобы отследить.
  6. В этом случае два фрагмента не эквивалентны, так как в "исключенном" null значение null будет означать, что остальная часть блока try будет пропущена. Конечно, sum будет по-прежнему правильной, но это просто совпадение.

Если вы действительно хотите повысить производительность, не используйте Integer и другие классы упаковки для простых вычислений, вместо этого используйте соответствующий примитив (int в этом случае). Дополнительный бонус этого заключается в том, что вам не придется больше беспокоиться о null потому что примитивные значения никогда не могут быть null.

Итак, подведите итог: никогда не делайте этого.

Серьезно, не надо. Каждый раз, когда вы это делаете, милый маленький котенок умирает. Изображение 174551

  • 0
    Возможно, единственное «правильное» использование try...catch здесь - обработать нулевую prism … кроме этого, я полностью согласен (но я не против, если несколько котят умрут: P)
  • 0
    Проголосовал бы, если бы не материал для котят ...;)
3

Вы никогда не должны использовать try-catch для управления потоком управления вашей программой.

Всегда используйте установленные методы, в этом случае проверяйте значение null, как и в первом примере кода.

0

Я знаю, что это не ответит на вопрос (можно 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;
}

И последнее, но не менее важное: обработка исключений медленнее, но обработка исключений в цикле медленнее.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню