2014-01-31 4 views
4

Требуется ли при использовании Java-7 try-with-resources для привязки к переменной? Короче говоря, этот блок кода ...Поведение try-with-resources с закрываемыми параметрами

try (final ObjectInputStream ois = new ObjectInputStream(
      new ByteArrayInputStream(data))) { 
     return ois.readObject(); 
    } 

Эквивалент к этому блоку? ...

try (final ByteArrayInputStream in = new ByteArrayInputStream(data); 
     final ObjectInputStream ois = new ObjectInputStream(in)) { 
     return ois.readObject(); 
    } 

Мое понимание Раздел 14.20.3 о Java Language Specification говорит, что они не являются одинаковыми и ресурсы должны быть назначены. Это было бы удивительно с точки зрения общего использования, и я не могу найти документацию, предупреждающую о шаблоне.

+0

не вернул бы этот объект, удерживая его ссылкой открытым (и, следовательно, не разрешая GC)? – SnakeDoc

+0

@SotiriosDelimanolis вы заметите, что я ссылался на тот же контент в моем вопросе ... –

+0

@AndrewWhite Ха-ха, я думаю, я неправильно понял ваш вопрос. Тавис, кажется, говорит лучше. –

ответ

3

Эти два блока не эквивалентны в том смысле, что они не будут генерировать один и тот же код. Но так как ObjectInputStream.close() вызовет close() на ByteArrayInputStream, что вы его передали, первый блок полностью в порядке.

EDIT: Что-то я забыл, так как в отличие от разумных конструкций, таких как new BufferedInputStream(new *InputStream(...)), конструктор ObjectInputStream действительно читает из потока, который вы его передаете, и, следовательно, может разумно генерировать исключение. По этой причине я бы рекомендовал второй блок, а не первый блок.

+2

Что делать, если 'new ObjectInputStream' бросает? – delnan

+0

@ delnan Очень хороший момент, я забыл, что конструктор 'ObjectInputStream' фактически читает из потока. –

2

Код не такой, как вы уже упоминали, поскольку Java будет генерировать закрытый блок для каждой переменной, даже если это необязательно. Что более важно, этот комментарий от JavaDocs на AutoCloseable:

Обратите внимание, что в отличие от близкого метода закрывающиеся, это близко метод не требуется идемпотентным. Другими словами, вызов этого метода более одного раза может иметь видимый побочный эффект, в отличие от Closeable.close, который не должен иметь эффекта, если вызвано больше , чем один раз. Однако разработчики этого интерфейса сильно поощряются к тому, чтобы их близкие методы были идемпотентны.

В основном это означает, что вызов close() дважды должны не иметь никакого эффекта, но не гарантируется. Поэтому рекомендуется избегать второй конструкции, которую вы представили, чтобы избежать двойного закрытия.

+0

Обратите внимание, что методы 'close()' ObjectInputStream' и 'ByteArrayInputStream' * являются * идемпотентными, поэтому в этом случае это не имеет значения. (На самом деле метод 'close()' ByteArrayInputStream' вообще ничего не делает.) –