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:
publicclassCircle{publicstaticvoidmain(String[] args){circleArea();}publicstaticvoidcircleArea(){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?
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.
Übrigens: Die Formel zur Berechnung der Kreisfläche ist falsch
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:
importjava.lang.Math;publicclassCircleimplementsAutoCloseable{publicstaticvoidmain(String[] args)throwsException{circleArea();}publicstaticvoidcircleArea(){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);}publicvoidclose()throwsException{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).
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
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.
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.)
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.
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.
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).
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.
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:
newBufferedInputStream(newFileInputStream("…"));
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.
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.
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.