#java #java.util.scanner
#java #eclipse #ввод #Ресурсы #утечки памяти
Вопрос:
Почему Eclipse выдает мне сообщение «Утечка ресурсов: «in» никогда не закрывается» в следующем коде?
public void readShapeData() {
Scanner in = new Scanner(System.in);
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
Комментарии:
1. Для будущих читателей: во многих ответах говорится, что вы должны закрыть сканер, чтобы закрыть базовый ресурс. Хотя в целом это верно, стандартный in является исключением. Его закрытие не позволит вам прочитать его снова, что обычно нежелательно. Как правило: не закрывайте то, что вы не открывали.
Ответ №1:
Потому что вы не закрываете свой сканер
in.close();
Комментарии:
1. Это закроет
Scanner
и отключит предупреждение, но оно также закроетсяSystem.in
, что обычно нежелательно.2. @StuartCook 1. Что-то, за чем нужно следить.
3. Зачем нам нужно закрывать сканер? Что подразумевается под «утечкой ресурсов»?
4. @nogard: этот ваш ответ действительно полезен.. но когда я использую in.close(); .. снова это показывает, что in не может быть разрешено.. у меня есть код без обработки исключений.. Спасибо
5. @StuartCook, вы забыли упомянуть, почему закрытие
System.in
обычно нежелательно. Это потому, что вы не сможете снова читать из него. Т. е. вы получитеjava.util.NoSuchElementException: No line found
, если попытаетесь вызвать(new Scanner(System.in)).nextLine()
, например.
Ответ №2:
Как говорили другие, вам нужно вызвать «close» для классов ввода-вывода. Я добавлю, что это отличное место для использования блока try — finally без подвоха, например:
public void readShapeData() throws IOException {
Scanner in = new Scanner(System.in);
try {
System.out.println("Enter the width of the Rectangle: ");
width = in.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = in.nextDouble();
} finally {
in.close();
}
}
Это гарантирует, что ваш сканер всегда закрыт, гарантируя надлежащую очистку ресурсов.
Аналогично, в Java 7 или более поздней версии вы можете использовать синтаксис «try-with-resources»:
try (Scanner in = new Scanner(System.in)) {
...
}
Комментарии:
1. Что подразумевается под утечкой ресурсов и как это повлияет на меня?
2. @Borat — «утечка ресурсов» подразумевает, что некоторый системный ресурс (обычно память) теряется или тратится без необходимости. Обычно это повлияет на вас, когда вы начнете получать ошибки OutOfMemoryErrors, возникающие во время нормальной работы вашей программы.
3. Спасибо, Эрик. Я знаю, что вы можете вызвать ошибку, добавив строку к самой себе в бесконечном цикле. Я не уверен, как сканер может вызвать эту ошибку.
4. Как насчет попытки с ресурсами?
5. Спасибо, Деннис, добавил.
Ответ №3:
Вам нужен call in.close()
в finally
блоке, чтобы убедиться, что это происходит.
Из документации Eclipse, вот почему он помечает эту конкретную проблему (выделение мое):
Классы, реализующие интерфейс java.io.Closeable (начиная с JDK 1.5) и java.lang.Считается, что автоматически закрываемые (начиная с JDK 1.7) представляют внешние ресурсы, которые следует закрыть с помощью метода close (), когда они больше не нужны.
Компилятор Eclipse Java способен анализировать, соответствует ли код, использующий такие типы, этой политике.
…
Компилятор отметит [нарушения] с помощью «Утечки ресурсов: «поток» никогда не закрывается».
Полное объяснение здесь.
Ответ №4:
Он сообщает вам , что вам нужно закрыть сканер , с помощью которого вы создали экземпляр System.in
Scanner.close()
. Обычно каждый ридер должен быть закрыт.
Обратите внимание, что если вы закроетесь System.in
, вы не сможете читать из него снова. Вы также можете взглянуть на этот Console
класс.
public void readShapeData() {
Console console = System.console();
double width = Double.parseDouble(console.readLine("Enter the width of the Rectangle: "));
double height = Double.parseDouble(console.readLine("Enter the height of the Rectangle: "));
...
}
Комментарии:
1. Обратите внимание, что
System.console()
это недоступно при запуске приложения через Eclipse, что может вызвать проблемы во время разработки.
Ответ №5:
// An InputStream which is typically connected to keyboard input of console programs
Scanner in= new Scanner(System.in);
приведенная выше строка вызовет конструктор класса сканера с аргументом System.in , и вернет ссылку на вновь созданный объект.
Он подключен к потоку ввода, который подключен к клавиатуре, поэтому теперь во время выполнения вы можете использовать пользовательский ввод для выполнения требуемой операции.
//Write piece of code
Чтобы устранить утечку памяти —
in.close();//write at end of code.
Ответ №6:
Если вы используете JDK7 или 8, вы можете использовать try-catch с ресурсами.Это автоматически закроет сканер.
try ( Scanner scanner = new Scanner(System.in); )
{
System.out.println("Enter the width of the Rectangle: ");
width = scanner.nextDouble();
System.out.println("Enter the height of the Rectangle: ");
height = scanner.nextDouble();
}
catch(Exception ex)
{
//exception handling...do something (e.g., print the error message)
ex.printStackTrace();
}
Комментарии:
1. Обратите внимание, что предложение catch не является обязательным. Если вы просто хотите убедиться, что ресурс закрыт даже в случае исключения, но оставляете обработку исключений как в исходном коде OP (а именно, вообще не перехватывается), вы можете просто использовать
try
, как показано, и не использоватьcatch
предложение.
Ответ №7:
добавление private static Scanner in;
на самом деле не устраняет проблему, оно только удаляет предупреждение. Статичность сканера означает, что он остается открытым навсегда (или до тех пор, пока класс get не выгрузится, что почти равно «навсегда»). Компилятор больше не выдает вам никаких предупреждений, поскольку вы сказали ему «держите его открытым навсегда». Но это не то, чего вы действительно хотели, поскольку вы должны закрыть ресурсы, как только они вам больше не понадобятся.
Привет, Манфред.
Ответ №8:
Ладно, серьезно, по крайней мере, во многих случаях это действительно ошибка. Это также отображается в VS Code, и это линтер, замечающий, что вы достигли конца охватывающей области, не закрывая объект сканера, но не признавая, что закрытие всех открытых файловых дескрипторов является частью завершения процесса. Утечки ресурсов нет, потому что все ресурсы очищаются при завершении, и процесс завершается, не оставляя места для хранения ресурса.
Ответ №9:
Вы должны закрыть свой сканер, когда закончите с ним:
in.close();
Ответ №10:
Как правило, экземпляры классов, которые имеют дело с вводом-выводом, должны быть закрыты после того, как вы закончите с ними. Итак, в конце вашего кода вы могли бы добавить in.close()
.
Ответ №11:
Сканер должен быть закрыт. Рекомендуется закрывать программы чтения, потоки … и такого рода объекты, чтобы освободить ресурсы и избежать утечек памяти aovid; и делать это в блоке finally, чтобы убедиться, что они закрыты, даже если при обработке этих объектов возникает исключение.
Комментарии:
1. Этот ответ на самом деле помогает OP узнать, почему он должен закрыть эту вещь. Конечно, он может прочитать документ и увидеть »
scanner.close()
«, но этот ответ действительно помогает ему / ей понять, что происходит. 1
Ответ №12:
private static Scanner in;
Я исправил это, объявив in как закрытую переменную класса статического сканера. Не уверен, почему это исправлено, но это то, что eclipse рекомендовал мне сделать.
Комментарии:
1. вы отключили предупреждение, но создали утечку ресурсов
Ответ №13:
Scanner sc = new Scanner(System.in);
//do stuff with sc
sc.close();//write at end of code.
Ответ №14:
in.close();
scannerObject.close();
Он закроет Scanner
и отключит предупреждение.