Вам не нужно многократные операторы close для любого из вложенных потоков и читателей в java.io. В конце концов, очень редко нужно закрывать более одной вещи в одном - большинство конструкторов могут выдавать исключение, поэтому вы пытаетесь закрыть вещи, которые вы еще не создали.
Если вы хотите закрыть поток независимо от того, успешно ли выполнено чтение, вам нужно вставить в finally.
Не присваивайте переменным значение null, а затем сравнивайте их, чтобы увидеть, произошло ли что-то раньше; вместо этого структурируйте свою программу так, чтобы путь, по которому вы закрывали поток, мог быть достигнут только в том случае, если исключение не выдается. Помимо переменных, используемых для итерации для циклов, переменные не должны изменять значение - я склонен отмечать все как окончательное, если нет необходимости делать иначе. Наличие флагов вокруг вашей программы, чтобы рассказать вам, как вы добрались до исполняемого в данный момент кода, а затем изменение поведения на основе этих флагов - это очень процедурный (даже не структурированный) стиль программирования.
То, как вы вкладываете блоки try / catch / finally, зависит от того, хотите ли вы по-разному обрабатывать исключения, выдаваемые различными этапами.
private static final String questionUrl = "/3095190/zakrytie-resursa-java";
public static void main ( String...args )
{
try {
final URLConnection connection = new URL ( args.length > 0 ? args[0] : questionUrl ).openConnection();
final BufferedReader br = new BufferedReader ( new InputStreamReader (
connection.getInputStream(), getEncoding ( connection ) ) );
try {
final String response = br.readLine();
System.out.println ( response );
} catch ( IOException e ) {
// exception handling for reading from reader
} finally {
// br is final and cannot be null. no need to check
br.close();
}
} catch ( UnsupportedEncodingException uee ) {
// exception handling for unsupported character encoding
} catch ( IOException e ) {
// exception handling for connecting and opening reader
// or for closing reader
}
}
getEncoding
необходимо проверить результаты соединений getContentEncoding()
и getContentType()
, чтобы определить кодировку веб-страницы; ваш код просто использует кодировку платформы по умолчанию, которая может быть неправильной.
Ваш пример, хотя и необычен в структурированном выражении, поскольку он очень процедурный; обычно вы должны разделить печать и получение в более крупной системе и позволить клиентскому коду обрабатывать любое исключение (или иногда перехватывать и создавать пользовательское исключение):
public static void main ( String...args )
{
final GetOneLine getOneLine = new GetOneLine();
try {
final String value = getOneLine.retrieve ( new URL ( args.length > 0 ? args[0] : questionUrl ) );
System.out.println ( value );
} catch ( IOException e ) {
// exception handling for retrieving one line of text
}
}
public String retrieve ( URL url ) throws IOException
{
final URLConnection connection = url.openConnection();
final InputStream in = connection.getInputStream();
try {
final BufferedReader br = new BufferedReader ( new InputStreamReader (
in, getEncoding ( connection ) ) );
try {
return br.readLine();
} finally {
br.close();
}
} finally {
in.close();
}
}
Как указывал Макдауэлл, вам может потребоваться закрыть входной поток, если выбрасывает new InputStreamReader
.