Java - Schließen des Scanners und Resource Leaks

8

Ich lerne Java und arbeite an einigen Projekten zum Spaß. Ein Problem, auf das ich hingewiesen habe, ist, dass wenn ich ein Scanner -Objekt verwende, Eclipse mich warnt:

  

Ressourcenverlust: "Scan" wird niemals geschlossen.

Also habe ich am Ende meines Codes ein scan.close(); hinzugefügt und das kümmert sich um die Warnung.

Das Problem tritt auf, weil ich andere Klassen im selben Paket habe, die auch Scannerobjekte verwenden, und Eclipse sagt mir, dass ich den Scanner in diesen Klassen schließen soll. Aber wenn ich das tue, scheint es, als würde es ALLE Scannerobjekte schließen und ich bekomme während der Laufzeit Fehler.

Hier ist ein Beispiel dafür, was den Fehler verursacht:

%Vor%

Nachdem der Scanner in der Klasse scanTest geschlossen wurde und die do-Schleife in test2 erneut eingegeben wird, tritt ein Fehler in der Zeile test = scan.nextInt();

auf

Ich habe versucht, die Erstellung des Scanner-Objekts in die do-Schleife zu verschieben, um jedes Mal ein neues Objekt zu erstellen, aber der Fehler tritt immer noch auf.

Ich bin mir nicht sicher, warum dies geschieht oder wie ich sicherstellen kann, dass alle meine E / A-Objekte geschlossen sind, ohne Probleme zu haben.

Ein Post, auf den ich stieß, erwähnte, dass, wenn System.in geschlossen ist, ich nicht wieder geöffnet werden kann. Wenn dies der Fall ist, müsste ich nur sicherstellen, dass ein Scanner-Objekt mit System.in am Ende des Programms geschlossen wird und alle anderen Scanner-Warnungen in anderen Klassen unterdrücken? Oder würde das alle Scannerobjekte offen lassen (schlecht)?

    
SuperCow 13.05.2014, 01:58
quelle

3 Antworten

3

Erstens ist das kein Speicherleck.

Zweitens schließt die Standardimplementierung beim Schließen eines Stream-Wrappers den Stream, den es umschließt. Dies bedeutet, dass Sie beim ersten Schließen des Scanners (wie beschrieben) ja System.in schließen.

Im Allgemeinen möchte man vermeiden, System.in zu schließen, wenn sie wieder von System.in lesen wollten. Der beste Weg, um dies zu tun, hängt von Ihrem Programm ab.

Man könnte die Information von System.in in einen Puffer irgendeiner Art kopieren und dann den Puffer scannen. Man könnte den Scanner nicht schließen und ihn an anderen Orten wiederverwenden. Man könnte sogar den Scanner für die Garbage-Collection de-referenzieren und mehrere neue Scanner auf System.in erstellen.

Diese Lösungen sind nicht alle gleichwertig, einige werden als viel besser angesehen als andere; aber alles hängt vom aufrufenden Programm ab. Experimentieren Sie mit ein paar, und wenn Sie auf ein Problem stoßen, öffnen Sie eine neue StackOverflow-Frage, in der Sie die relevanten Teile Ihres Codes, eine Beschreibung des Problems, die Beispieleingabe und die falsche Ausgabe (zusammen mit der gewünschten Ausgabe) anzeigen.

Viel Glück.

    
Edwin Buck 13.05.2014 02:01
quelle
3

Ja, wenn Sie einen Scanner schließen, schließen Sie den zugrunde liegenden Stream (in diesem Fall System.in). Um dies zu vermeiden, erstellen Sie entweder eine globale Variable des Scanners, die von allen Klassen verwendet werden kann, oder einen zentralen Punkt zum Herunterfahren des Scanners (kurz bevor das Programm beendet wird)

    
Scary Wombat 13.05.2014 02:07
quelle
0

Benennen Sie nicht alle Ihre Scanner gleich. Wenn Sie in einer Sache mehrere haben:

%Vor%

Geben Sie die *scanner name goes here*.close(); für jeden Ihrer Scanner ein. Wenn sie alle denselben Namen haben, dann ändere diejenigen, die etwas anderes als andere Scanner tun.

    
TheTNTwither James 29.08.2017 18:42
quelle

Tags und Links