Использование обработки исключений для выполнения потока управления - когда нет необходимости из-за API - это плохая практика.
Если ваша причина для этого состоит в том, чтобы вы могли писать заявления на одной строке, вы должны оценить причины, по которым вы считаете, что лучше писать инструкции на одной строке. Мой телефон имеет достаточно большой экран, чтобы одновременно отображать все четыре примера выше, и я не кодирую на своем телефоне, поэтому я не могу представить ситуацию, когда пишу что-то по одной строке, потому что я могу написать это на одной линии "- достаточно убедительная причина.
Кроме того, считают ли на самом деле делает тот факт, что вы можете написать некоторые из заявлений по одной строке кода короче в целом:
while (true) {
try {
output.write(buffer, 0, input.read(buffer, 0, buffer.length);
} catch (ArrayIndexOutOfBoundsException e) {
break;
}
}
(я не обращая внимания на IOException
здесь, как вы в первых трех примерах - его нужно обрабатывать, однако вы пишете код, поэтому он не имеет значения для разницы между 4 версиями с точки зрения количества кода).
Сравните это эквивалентный код от подхода 2 (ближайший эквивалент):
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
который намного более кратким.
Но, как я уже упоминал выше, краткость кода на самом деле не является мерой качества кода, поэтому сама по себе это не повод отклонить предлагаемую версию. Тем не менее, есть и более фундаментальные причины, почему это не хороший подход ...
В предлагаемом коде, есть два ожидаемые типа исключения: IOException
и ArrayIndexOutOfBoundsException
. Эти исключения из принципиально иной природы:
The IOException
, как ожидается, в результате чтения или записи неудачи (который является фактическим исключительным условием, и, следовательно, является подходящим использованием исключения).
IOException
является проверено исключение. Проверяемые исключения должны обрабатываться (это ошибка времени компиляции). Они предназначены для указания восстановительных условий и условий, которые не поддаются контролю API. Например, если вы пишете на диск или в сети, вы не можете контролировать, заполняется ли диск другим процессом или если подрядчики, выкапывающие дорогу, собираются сократить ваше оптоволоконное соединение. Проверенные исключения указывают на то, что «это может быть успешным, если вы попробуете еще раз позже» (когда диск не будет полным, или подрядчики зафиксировали волокно)
Ожидается, что ArrayIndexOutOfBoundsException
будет достигнуть конца входного потока (что не является исключительным условием, так как почти все потоки заканчиваются и, следовательно, не являются надлежащим использованием исключения и не являются необходимым использованием исключения, поскольку оно обнаруживается с помощью возвращаемых значений чтения).
ArrayIndexOutOfBoundsException
is unchecked исключение, возникающее из-за ошибки в программировании - с использованием API таким образом, который он не предназначен для использования. Неконтролируемые исключения не нужно обрабатывать (это не ошибка времени компиляции, если вы этого не сделаете), поскольку они предназначены для указания в основном неустранимых условий, таких как ошибки программирования. Например, если вы попытаетесь запустить какой-то код с определенным входом, и он выдает исключение из-за ошибки программирования, он выкинет одно и то же исключенное исключение позже, потому что он работает с тем же кодом.
Таким образом, в то время как вы можете поймать и восстановить из непроверенных исключений, то есть не то, что они были предназначены для (именно поэтому вы не имеют к). Легче написать код, чтобы исключение не происходило в первую очередь.
И это легко в этом случае: Javadoc for OutputStream
говорит:
Если off
отрицательные, или len
отрицательные, или off+len
больше, чем длина массива b
, затем IndexOutOfBoundsException
брошен.
Итак, соблюдайте эти условия, и вам не нужно беспокоиться об этом.
(И вы должны были ловить IndexOutOfBoundsException
вместо ArrayIndexOutOfBoundsException
в любом случае, потому что некоторые реализации OutputStream
не может бросить последний.)
Но есть и более глубокая причина, почему вы не должны полагаться на ловле исключенные исключения для вашего потока управления: , вы не можете обнаружить состояние, которое, по вашему мнению,.
является неконтролируемым исключение любого типа может быть выброшено из любого места в цепочке вызовов конкретного вызова - Вы могли бы ожидать , что это происходит потому, что OutputStream.write
не нравится отрицательный len
параметра, но он может на самом деле вызывать все остальное в OutputStream.write
- или в InputStream.read
- или в любом из других методов, которые они называют транзитивно, - вы не можете точно сказать (не проверяя трассировку стека, однако детали того, что вы должны проверять трассировку стека поскольку они специфичны для реализации, и, таким образом, потребуется много усилий, чтобы сделать это достаточно прочным).
Если вы рассматриваете это исключение как значение, которое вы достигли конца потока, вы можете фактически маскировать некоторые другие проблемы в коде, который вам нужен . знать.
Итак, лучше всего написать код, чтобы он не полагался на обнаружение определенного неконтролируемого исключения. В тех случаях, когда это задокументировано, что он будет вызывать такое исключение при определенных обстоятельствах, избегать этих обстоятельств.
Использование обработки исключений для выполнения потока управления - особенно когда это не нужно из-за API - это плохая практика. –
«Одиночная строка для чтения и записи !!!!» Позор по всем другим дополнительным линиям. –
@ AndyTurner благодарит вас Andy, когда 'InputStream.read (...)' возвращает '-1' вызывается ArrayIndexOutOfBoundsException, тогда необходимо отделить строки для чтения и записи. Но какова альтернатива 'catch (ArrayIndexOutOfBoundsException e)', используя только одну строку? –