Try-catch для деления на ноль

Я новичок в java, мой вопрос касается блоков try-catch на простом делении на нулевом примере. Вы видите первую попытку? Если я перенесу любую из этих двух переменных в двойную, программа не распознает блок catch. На мой взгляд, должен ли я запускать или не только блокирующий блок. Что не так в этом коде? Спасибо.

public static void main(String[] args) {

    int pay=8,payda=0;  

    try {

        double result=pay/(double)payda; // if I cast any of the two variables, program does not recognize the catch block, why is it so?
        System.out.println(result);
        System.out.println("inside-try");


    } catch (Exception e) {

        System.out.println("division by zero exception");
        System.out.println("inside-catch");

    }
}

Ответы

Ответ 1

Деление на ноль допустимо для чисел с плавающей запятой.

  • 1/0 дает бесконечность.
  • (- 1)/0 дает -Infinity.
  • 0/0 дает NaN.

Эти "цифры" правильно определены в IEEE 754.

Целочисленное деление на ноль, с другой стороны, бросает, потому что невозможно представить бесконечность как int.

Ответ 2

Я предлагаю проверить:

if (divisor != 0) {
    // calculate
}

вместо того, чтобы перехватывать исключение

Ответ 3

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

  • Если ожидается исключение, оно обычно проще, яснее и эффективнее, если вы обнаружите условие, которое приведет к возникновению исключения. В этом случае, если вы ожидаете, что divisor будет иногда нулевым, лучше проверить его перед делением.

  • С другой стороны, если исключение совершенно неожиданно (т.е. "ошибка" ), лучшая стратегия заключается в том, чтобы исключение распространялось на самый внешний уровень. В этот момент ваш захват приложения должен ловить все исключения, регистрировать исключение stacktrace и выходить из системы.

  • Помимо предыдущей пули, неплохо поймать Exception, RuntimeException, Throwable или Error. Это приведет к большому количеству исключений, которые вы, вероятно, не собираетесь ловить. В этом случае, поскольку вы ожидаете ArithmeticException, вы должны поймать только это.

  • Редко правильно использовать float или double в финансовых приложениях. Эти типы не являются точными, но для финансовых приложений обычно требуется точное количество денег.

  • В более общем плане числа с плавающей запятой изначально трудно усложнять людям (и новичкам). Многие "истины", которые люди ожидают провести, на самом деле не выдерживают. Например, вычисление с плавающей запятой 1.0/3.0 + 1.0/3.0 + 1.0/3.0 не дает 1.0. Аналогично (как вы обнаружили) деление на ноль ведет себя по-разному. Если вы хотите безопасно использовать плавающие точки, вам необходимо понять подводные камни.

РЕДАКТИРОВАТЬ, в котором будет высвечиваться первая точка в ответ на комментарий @Jay.

Во-первых, я сознательно использовал слово "обычно". Бывают случаи, когда избегать выброса ожидаемого исключения ничего не достигает.

Сказав это, вы часто не хотите, чтобы генерическое "ожидаемое" исключение происходило даже в том случае, если ваше приложение не может сразу разобраться с ситуацией. Например, если код OP был частью чего-то большего, может быть лучше явно бросить IllegalArgumentException (если это нарушение контракта API) или некоторые отмеченные UserEnteredRubbishException, если мы знаем, что это результат плохого пользовательский ввод (и есть некоторая возможность сообщить/исправить его).

Тот факт, что мы "ожидаем" исключение, по определению означает, что мы знаем об этом больше, чем (скажем) общий ArithmeticException. Если мы разрешаем распространение общего исключения, это затрудняет работу блока catch с множеством стековых фреймов. В этом случае, например, удаленный блок блокировки не мог диагностировать причину деления на ноль с какой-либо определенностью. ArithmeticException может быть получен из другой части приложения и может даже не быть делением на нуль! Способ обращения заключается в явном бросании более конкретного исключения.

Ответ 4

Ответ лежит на вашей собственной программе - он печатает "Бесконечность" для result. Это связано с тем, что Java только запрещает целочисленное деление на ноль - деление с плавающей запятой на ноль является законным и создает Infinity.

Смотрите документацию Double и Float для констант POSITIVE_INFINITY и NEGATIVE_INFINITY.

Ответ 5

Только деление на ноль с целыми значениями приведет к возникновению исключения ArithmeticException. Деление на ноль с двойным или плавающим результатом приведет к Бесконечность.

Ответ 6

Потому что деление двух удвоений возвращает бесконечность, но не бросает. Вы можете использовать isInfinite(), чтобы проверить это. Однако подходящее решение (как уже отмечалось) - проверить знаменатель перед делением.

Ответ 7

Никто не должен ожидать, что RuntimeException будет выброшен из их кода. Эти Exception могут (и должны быть) легко устранены.