Это безопасный способ освободить ресурсы в Java? - PullRequest
1 голос
/ 25 апреля 2010

Обычно, когда коду нужен какой-то ресурс, который должен быть освобожден, я вижу, что это сделано так:

InputStream in = null;
try{
    in = new FileInputStream("myfile.txt");
    doSomethingWithStream(in);
}finally{
    if(in != null){
        in.close();
    }
}

Что мне не нравится, так это то, что вам нужно инициализировать переменную в null и после этого набораэто к другому значению и в блоке finally проверьте, был ли ресурс инициализирован, проверяя, является ли он нулевым.Если это не нуль, это должно быть выпущено.Я знаю, что придираюсь, но я чувствую, что это можно сделать чище.

Я хотел бы сделать следующее:

InputStream in = new FileInputStream("myfile.txt");
try{
    doSomethingWithStream(in);
}finally{
    in.close();
}

На мой взгляд, это выглядит почти так же безопасно, какпредыдущий.Если инициализация ресурса завершается неудачно и возникает исключение, ничего не поделаешь (так как я не получил ресурс), поэтому он не должен находиться внутри блока try.Единственное, что меня беспокоит, так это если есть какой-то способ (я не сертифицирован Java), что между операциями может быть выдано исключение или ошибка?

Еще более простой пример:

Inputstream in = new FileInputStream("myfile.txt");
in.close();

Есть ли какой-нибудь способ оставить поток открытым, что бы помешал блок try-finally?

Редактировать:

Может быть, я должен был пропустить последний пример, потому чтоэто смущает всех.Это не должно быть вопросом начального уровня.Я знаю, что делает try-finally, и я знаю, что небезопасно, если в последнем примере в середине был doSomethingWithStream.Вот почему его там нет.Я принял ответ Eyals, потому что это было именно то, что я искал.Есть способ вызвать исключение между двумя операциями, что сделало бы средний пример небезопасным (используя Thread.stop), но, поскольку он сделан с использованием устаревшего вызова и может испортить вас, независимо от того, что вы делаете, я чувствую себя в безопасности, используясредний пример.

Ответы [ 3 ]

2 голосов
/ 25 апреля 2010

Средний образец безопасен, последний - нет.

Блок try-finally означает, что поток закрывается, даже если doSomethingWithStream выдает исключение. Да, вы можете перехватить все исключения и затем закрыть поток таким образом, но гораздо проще позволить исключению всплыть до вызывающей стороны, но закрыть поток по пути через блок finally.

1 голос
/ 25 апреля 2010

На самом деле между двумя вызовами в последнем примере кода может возникнуть исключение, и ресурс останется открытым. Если поток принудительно останавливается другим потоком с помощью Thread.stop () или Thread.stop (Throwable) сразу после создания потока, поток сгенерирует исключение (ThreadDeath в первом случае), и ресурсы не будут удалены из.

Но именно поэтому эти методы устарели ...

0 голосов
/ 26 апреля 2010

Загляните в Проект Ломбок . Он имеет аннотацию @Cleanup, которая устанавливается для локальных переменных, которые автоматически генерируют код во время компиляции для очистки ресурса.

 import lombok.Cleanup;
 import java.io.*;

 public class CleanupExample {
   public static void main(String[] args) throws IOException {
     @Cleanup InputStream in = new FileInputStream(args[0]);
     @Cleanup OutputStream out = new FileOutputStream(args[1]);
     byte[] b = new byte[10000];
     while (true) {
       int r = in.read(b);
       if (r == -1) break;
       out.write(b, 0, r);
     }
   }
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...