Обработка исключений try catch different behavior [duplicate]

Математическая математика с плавающей запятой такова. В большинстве языков программирования он основан на стандарте IEEE 754 . JavaScript использует 64-битное представление с плавающей запятой, которое совпадает с Java double. Суть проблемы состоит в том, что числа представлены в этом формате как целое число раз в два раза; рациональные числа (такие как 0.1, который является 1/10), знаменатель которого не является степенью двух, не могут быть точно представлены.

Для 0.1 в стандартном формате binary64 представление может записывается в точности как

  • 0.1000000000000000055511151231257827021181583404541015625 в десятичной форме или
  • 0x1.999999999999ap-4 в нотации C99 hexfloat .

Напротив, рациональное число 0.1, которое является 1/10, может быть записано точно как

  • 0.1 в десятичной форме или
  • 0x1.99999999999999...p-4 в аналоге обозначения гексафлоата C99, где ... представляет собой бесконечную последовательность 9.

Константы 0.2 и 0.3 в вашей программе также будут приближенными к их истинные ценности. Бывает, что ближайший double до 0.2 больше, чем рациональное число 0.2, но ближайший double до 0.3 меньше, чем рациональное число 0.3. Сумма 0.1 и 0.2 заканчивается выше, чем рациональное число 0.3 и, следовательно, не согласуется с константой в вашем коде.

Достаточно полное рассмотрение арифметических вопросов с плавающей запятой Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой . Для более простого объяснения см. floating-point-gui.de .

14
задан David Newcomb 3 February 2016 в 17:56
поделиться

6 ответов

А RuntimeException может быть брошен любым кодом. Другими словами, компилятор не может легко предсказать, какой код может его бросить. А RuntimeException может быть захвачен блоком catch(Exception e).

IOException, однако, является проверенным исключением - только вызовы метода, объявленные для его броска, могут это сделать. Компилятор может (разумно) уверенно, что это невозможно, если нет вызовов методов, которые объявляются для его броска.

Компилятор Java просто не считает, что «нет никакого кода вообще блок «try block» - он всегда позволяет вам исключать неконтролируемые исключения, так как во всех разумных сценариях будет существовать код, который мог бы потенциально выбросить исключенное исключение.

Из раздела раздела 14.21 JLS:

Блок catch C доступен, если выполняются оба значения:

  • ] Некоторый оператор выражения или throw в блоке try доступен и может генерировать исключение, тип которого присваивается параметру предложения catch. (Выражение считается достижимым, если внутреннее утверждение, содержащее его, доступно.)
  • В заявлении try нет ранее блока catch A, так что тип параметра C такой же, как или подкласс типа параметра A.

Возможно, компилятор должен понять, что в вашем блоке есть no выражения в блоке try ... похоже, что это еще недостижимое предложение catch , для меня.

EDIT: Как отмечено в комментариях, в разделе 14.20 содержится следующее:

Это ошибка времени компиляции, если a catch исключает тип исключенного исключения E1 , но не существует типа исключенного исключения E2 , для которого выполняются все следующие функции:

  • E2 & lt ;: E1
  • Блок try, соответствующий предложению catch, может вызывать E2
  • Ни один предшествующий блок catch непосредственно входящего оператора try не улавливает E2 или супертип E2 .

, если только E1 - это исключение класса.

Итак, похоже, что вы на самом деле на самом деле , но spec не насколько это было возможно в плане недостижимых блоков catch в 14 0,21.

25
ответ дан Jon Skeet 27 August 2018 в 22:37
поделиться

Поскольку для отмеченных исключений метод, который их выбрасывает, должен явно указывать этот факт ключевым словом «throws», поэтому, если в вашем блоке нет «throws IOException», у компилятора есть информация, g0] невозможно для исключения IOException, поэтому все, что вы делаете после ловли, было бы недостижимым.

2
ответ дан abalogh 27 August 2018 в 22:37
поделиться

IOException - это исключенное исключение, которое генерируется только кодом, связанным с IO. Поскольку ваш блок try ничего не делает, ничто не связано с IO, IOExceptions никогда не будут выбрасываться, поэтому блокировки catch никогда не будут выполняться, и компилятор не позволит вам обойтись с ним. Как вы сказали, исключение может относиться к неконтролируемым исключениям времени выполнения, которые могут произойти в любой момент. В этом основное отличие между исключениями и проверенными исключениями, поэтому компилятор не применяет код, чтобы уловить все возможные исключения во время выполнения.

1
ответ дан Anthony Accioly 27 August 2018 в 22:37
поделиться

Исключения IO могут быть обнаружены только в том случае, если компилятор предсказывает, что в коде может быть что-то, что вызывает IOException. Таким образом, вы получаете предупреждение о том, что исключение IO никогда не выбрасывается из тела оператора try (поскольку в теле try нет ничего).

5
ответ дан APerson 27 August 2018 в 22:37
поделиться

Вы не можете перехватывать исключенные проверенные исключения, потому что их нельзя выбросить. Вы можете поймать Exception, потому что неконтролируемое исключение во время выполнения - это Exception и потенциально могут быть выброшены.

3
ответ дан Isaac Truett 27 August 2018 в 22:37
поделиться

Просто Java предполагает, что любая строка кода может генерировать общий Exception или Throwable, т.е. OutOfMemoryException, который является Error, а не Exception. То же самое относится к NPE.

IOException является конкретным исключением, которое может быть выбрано только управляемым кодом, поэтому, если у вас нет вызовов ввода-вывода в вашем блоке catch, ваш компилятор не имеет шансов

Просто, чтобы сравнить с C # world, в C # такой код будет скомпилирован, но будет концептуальной ошибкой, так как если вы не сделаете ничего, что вы не достигнете блока catch. Инструмент, такой как ReSharper, может предупредить вас об этом.

0
ответ дан usr-local-ΕΨΗΕΛΩΝ 27 August 2018 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: