Warnung in Eclipse: unassigned closeable value

Sw4rls

Mitglied
Hallo,

ist mein erster Post hier. Ich fange gerade an, mir Java selbst beizubringen. Ich bin also noch ziemlicher Anfänger, aber bringe schon kleine Miniprogrämmchen zustande. Ich benutze Eclipse und bekomme eine Warnung bei folgendem Code:

Java:
public class Circle
{
	
	public static void main(String[] args)
	{
		
		circleArea();
		
	}
	
	public static void circleArea()
	{
		
		System.out.println("Bitte Radius des Kreises angeben:");
		double radius = new java.util.Scanner(System.in).nextDouble();
		System.out.println("Die Flaeche des Kreises betraegt");
		System.out.println(2 * radius * radius * Math.PI);
		
		
	}
}

Die Warnung ist für diese Zeile:
Code:
double radius = new java.util.Scanner(System.in).nextDouble();
und lautet:
- Resource leak: '<unassigned Closeable value>' is never closed

Was habe ich falsch gemacht? Wie muss ich den Code korrigieren, damit die Warnung nicht mehr erscheint?

Danke im Voraus für hilfreiche Antworten.

Sw4rls
 
Die Meldung besagt einfach, dass du den Scanner besser mit .close() schließen solltest.
Die Warnung kannst du bei deinem kleinen Mini-Programm aber auch ruhig ignorieren,
 
Ja, du hast ja recht ... aber wenn jemand gerade mit dem Programmieren anfängt, dann gibt es vermutlich erst mal wichtigeres, dass es zu verstehen gilt.
Es gibt wichtigeres? Na dann, gut Nacht wenn du schon so anfängst, wie werden die großen Programme mal aussehen? Ordnung und Leserlichkeit ist dass wichtigste, und wenn man ganz viele kleine Fehler Ignoriert, kommt am ende auch ein großes Problem raus.
 
Erst mal danke für die Antworten. Leider werde ich aus den beiden Links nicht direkt schlau. Ich verstehe, dass man den Scanner wieder schließen sollte, wenn er nicht mehr gebraucht wird. Aber wie gebe ich das jetzt syntaktisch an?

Also mein Code sieht jetzt so aus:

Java:
import java.lang.Math;

public class Circle implements AutoCloseable
{
	
	public static void main(String[] args) throws Exception
	{
		
		circleArea();
		
	}
	
	public static void circleArea()
	{
		
		System.out.println("Bitte Radius des Kreises angeben:");
		double radius = new java.util.Scanner(System.in).nextDouble();
		System.out.println("Die Flaeche des Kreises betraegt");
		System.out.println(radius * radius * Math.PI);
		
		
	}

	public void close() throws Exception
	{
		
		System.out.println("Die Fläche des Kreises ist berechnet.");
		
	}
}
(Ja, ich habe die Formel auch gleich verbessert 😀)

Ich habe noch nicht ganz verstanden, wie das genau funktioniert. Vielleicht kann mir jemand das möglichst einfach erklären (oder zumindest sagen, was in meinem code noch fehlt).
 
Damit du den Scanner wieder schließen kannst, musst du ihn zuvor einer Scanner-variablen zuweisen. Etwa so:

Java:
Scanner scanner = new Scanner();
// ( mache was mit dem Scanner)
scanner.close();
 
Die Warnung sagt nur aus, dass du einen von vielen Eclipse-Bugs entdeckt hast. 😀
[JAPI]System#in[/JAPI] sollte man wohl nicht schließen.
 
Man wird gewarnt, dass man den Scanner nicht geschlossen hat, welcher
Code:
System.in
wrappt.
Allgemein braucht man ihn doch nicht zu schließen, wenn er per [JAPI]Scanner#Scanner(java.io.InputStream)[/JAPI] erzeugt wurde. Dabei wird ja kein neuer Stream geöffnet oder dergleichen. Der unterliegende Stream muss lediglich irgendwann geschlossen werden. Es sei denn, es handelt sich um
Code:
System.in
. Oder habe ich etwas verpasst?
 
Oder habe ich etwas verpasst?
Wie man's nimmt. Jedenfalls würfelst du gerade viele verschiedene Sachen durcheinander. 😉

Allgemein braucht man ihn doch nicht zu schließen, wenn er per [JAPI]Scanner#Scanner(java.io.InputStream)[/JAPI] erzeugt wurde. Dabei wird ja kein neuer Stream geöffnet oder dergleichen. Der unterliegende Stream muss lediglich irgendwann geschlossen werden.
Das ist zwar richtig, aber hier gar nicht von Belang. Der Parser orientiert sich nur an AutoCloseable, und da Scanner dieses Interface implementiert, kommt eine entsprechende Warnung. Der Scanner hätte genausogut auch mit [c]new Scanner(new File("foo.txt"))[/c] erzeugt werden können, da würde dein Argument nicht mehr ziehen. 😉

Und außerdem hat das noch nicht einmal was mit Eclipse zu tun. Wie gesagt, es liegt an AutoCloseable beim Scanner, und dafür kann Eclipse nichts.

Es sei denn, es handelt sich um
Code:
System.in
.
Nicht nur. Es hätte auch jeder x-beliebige andere InputStream sein können, der eigentlich nicht geschlossen werden muss. Aber der Parser kann nicht entscheiden, wann es notwendig ist und wann nicht. Das kann man als Entwickler nur der Dokumentation entnehmen. (Und selbst dann wird es wohl kaum falsch sein, den Datenstrom sauber zu schließen.)

Ark
 
Das ist zwar richtig, aber hier gar nicht von Belang. Der Parser orientiert sich nur an AutoCloseable, und da Scanner dieses Interface implementiert, kommt eine entsprechende Warnung. Der Scanner hätte genausogut auch mit [c]new Scanner(new File("foo.txt"))[/c] erzeugt werden können, da würde dein Argument nicht mehr ziehen. 😉
Und genau das ist das Problem. Das wurde einfach schlecht/fehlerhaft implementiert. Man hätte zwischen den Konstruktoren unterscheiden können.

Und außerdem hat das noch nicht einmal was mit Eclipse zu tun. Wie gesagt, es liegt an AutoCloseable beim Scanner, und dafür kann Eclipse nichts.
Das hat sehr wohl etwas mit Eclipse zu tun. Diese Warnung kommt von Eclipse und seinem Parser, nicht von
Code:
javac
.

Aber der Parser kann nicht entscheiden, wann es notwendig ist und wann nicht.
In diesem Fall wäre es gegangen. In Fällen, in denen das nicht gegangen wäre, hätte er einfach gar nichts sagen sollen. Für mich ist das einfach eine falsche Warnung.
 
Und genau das ist das Problem. Das wurde einfach schlecht/fehlerhaft implementiert. Man hätte zwischen den Konstruktoren unterscheiden können.
Hm, und wie genau? Mit Annotations? Mit Interfaces (=jetzige Lösung) stelle ich mir das jedenfalls etwas schwierig vor …

Das hat sehr wohl etwas mit Eclipse zu tun. Diese Warnung kommt von Eclipse und seinem Parser, nicht von
Code:
javac
. … Für mich ist das einfach eine falsche Warnung.
Ich habe mir gerade mal den entsprechenden Abschnitt der Sprachspezifikation durchgelesen, und da fand ich jetzt keinen Hinweis darauf, wie so etwas vom Parser zu behandeln ist. Insofern stimmt es natürlich, dass dieses Verhalten Eclipse-spezifisch ist. Aber es ist, wenn ich das richtig verstanden habe, auch kein fehlerhaftes Verhalten. Wenn es dich stört, kannst du die Warnung abschalten (sollte gehen).

In Fällen, in denen das nicht gegangen wäre, hätte er einfach gar nichts sagen sollen.
Und da ist das Problem: Finde einen Algorithmus, der für alle Java-Quelltexte in endlicher Zeit und mit endlichem Speicher korrekt entscheiden kann, ob "das gegangen wäre" oder nicht.

Ich bin übrigens der Meinung, dass in diesem Fall der Fehler eher in den angebotenen Konstruktoren von Scanner zu suchen ist. Meiner Meinung nach hätte es für jeden Konstruktor nur eine für alle Konstruktoren identische Möglichkeit geben dürfen, die Eingabe festzulegen, und zwar über CharSequence. Dann bräuchte ein Scanner auch kein Closeable, geschweige denn ein AutoCloseable.

Ark
 
Zuletzt bearbeitet:
Mit Interfaces (=jetzige Lösung) stelle ich mir das jedenfalls etwas schwierig vor …
Hmm, hier wird wohl das Problem sein. Man müsste im Prinzip zwischen echten Ressourcen und Wrappern unterscheiden.
Hierbei ist eigentlich auch nur der "richtige" Stream zu schließen:
Java:
new BufferedInputStream(new FileInputStream("…"));
Am Ende schließt man diesen aber über den Wrapper, weil man in der Regel keine Referenz mehr hat.

Ist in der Tat also nicht leicht zu machen. Ich finde dieses Verhalten jedenfalls problematisch, wenn man keine einzige Warnung im Code haben will. So muss man diese im Allgemeinen hilfreiche Warnung wegen der einen Falschmeldung ausstellen.

Wenn es dich stört, kannst du die Warnung abschalten (sollte gehen).
Ist nicht nötig, weil ich durch die drastische Performanceeinbuße bei Juno umgestiegen bin. NetBeans hat wiederum natürlich auch seine Macken …
 
Hm, also lautet der Konsens nun, dass ich den ursprünglichen Code also ohne in schlechtem Stil zu schreiben, stehen lassen kann?

Jedenfalls bekomme ich die Warnung, was ich auch versuche, nicht weg. Und da ich nicht Tage damit verbringen will, werde ich erst mal weiter lernen und mich des Problems annehmen, wenn ich später nochmal darauf treffe.

Danke jedenfalls für alle Antworten!
 
Netbeans zeigt übrigens keine Fehlermeldung.

Guter Stil wäre in diesem Fall:

Java:
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("Bitte Radius des Kreises angeben:");
        double radius = Double.parseDouble(reader.readLine());
        System.out.println("Die Flaeche des Kreises betraegt: " + radius * radius * Math.PI);

+ throws IOException
 
Ok, also wenn ich den Code so schreibe:

Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.Math;

public class Circle
{
	
	public static void main(String[] args) throws IOException
	{
		
		circleArea();
		
	}
	
	public static void circleArea() throws IOException
	{
		
	    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
	    System.out.println("Bitte Radius des Kreises angeben:");
	    double radius = Double.parseDouble(reader.readLine());
	    System.out.println("Die Flaeche des Kreises betraegt: " + radius * radius * Math.PI);
		
	}
}

gibt mir Eclipse weder Warnung noch Fehler aus. So werde ich es also lassen. Vielen Dank!
 
"unassigned Closeable value" bedeutet ja etwas wie "Nicht-zugewiesene schließbare Variable wird nicht geschlossen"

Finde die Warnung auch unnötig. IDE s sind eben auch nicht fehlerfrei

Am Besten wärs, du würdest dich nicht weiter um solche Meldungen kümmern und mit OOP weitermachen (eigene Kreis-Klasse schreiben)
 
Mein Ansinnen ist eigentlich, ein Programm zu schreiben, dass einem Körper ausrechnet und später vielleicht Optimierungsmöglichkeiten aufzeigt.

Also So was wie:

- Diese Zylinderförmige Verpackung hat das und das Volumen.
- Wenn Ich ein bestimmtes Volumen haben möchte, wie sollten Radius und Höhe dann am besten aufgeteilt sein, damit ich möglichst wenig Material brauche?
- Auch anders herum: Wenn ich nur bestimmtes Material zur Verfügung habe, wie forme ich dann den Zylinder um möglichst viel Volumen zu bekommen?

Bis dahin hab ich noch ein bisschen Weg, aber ich denke das sollte machbar sein.
Jetzt wird es aber doch ein bisschen Off-Topic.
 
Mit anderen worten, formel für radius, höhe und volumen ableiten und minimum bestimmen. Radius und höhe stehen ja immer im denselben verhältnis.[/OT]

Gesendet von mit Tapatalk 2
 
Zuletzt bearbeitet von einem Moderator:

Zurück
Oben