Ответ 1
Если вы разделите код следующим образом, будет ли предупреждение уходить?
Scanner scanner = new Scanner(a);
scanner.useDelimiter(",");
scanner.close();
Это мой код:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
public class temp {
public static void main(String[] args) throws FileNotFoundException {
BufferedReader a = new BufferedReader(new FileReader("a"));
Scanner scanner = new Scanner(a).useDelimiter(",");
scanner.close();
}
}
Я получаю предупреждение в new Scanner(a)
, который говорит (я компилирую с помощью jdk1.7.0_05.):
Resource leak: '<unassigned Closeable value>' is never closed.
Я что-то делаю неправильно, или это просто ложное предупреждение?
Если вы разделите код следующим образом, будет ли предупреждение уходить?
Scanner scanner = new Scanner(a);
scanner.useDelimiter(",");
scanner.close();
Да, ваш код имеет потенциальную (но не реальную) утечку памяти. Вы присваиваете возвращаемое значение useDelimiter(a)
локальной переменной scanner
, но результат конструктора выбрасывается. Вот почему вы получаете предупреждение.
На практике возвращаемое значение useDelimiter(a)
- это точно тот же объект, что и возвращаемый из вызова конструктора, поэтому ваш код просто отлично закрывает ресурс. Но это то, что инструмент анализа компилятора/кода не может обнаружить, поскольку он должен был бы знать реализацию useDelimiters для этого.
И действительно хороший инструмент анализа кода должен был показать вам дополнительное предупреждение, потому что вы закрываете ресурс, который не был открыт в этом методе (возвращаемое значение useDelimiter). Если бы у вас были эти 2 сообщения вместе, симптомы могли бы быть более понятны вам.
Попробуйте:
Scanner scanner = new Scanner(new BufferedReader(new FileReader("a"))).useDelimiter(",");
Если это не сработает, вы должны добавить a.close();
Что дает вам это предупреждение? Предположительно он предупреждает, потому что выделение/закрытие не выполняется в блоке try/finally, что, как правило, плохое (в данном конкретном случае это не проблема, потому что единственное, что может вызвать ошибку, это новый FileReader, и если это ни один ресурс не был выделен - но это может измениться с помощью одного вызова метода.)
Закрытие сканера закрывает базовый поток (точнее, все, что реализует себя Closeable
(да BufferedReader
), поэтому код отлично от него.