Java: Immer noch keine echten Templates?
-
Ist es denn garantiert das finalize aufgerufen wird? AFAIK ist es das nicht.
es ist garantiert das finalize aufgerufen wird. das wird es immer. allerdings ist nicht garantiert WANN finalize aufgerufen wird, weil es eben vom GC aufgerufen wird bevor das objekt verworfen wird.
wie bereits Zeus sagte haben solche "teuren" objekte dafuer methoden.
close() zB schliesst eine connection. dieses connection objekt hat jetzt keine verbindung mehr mit der DB. das heisst du weisst das dein connection objekt zu ist. es wird nun aber nicht gleich aus dem speicher genommen - erst wenn der GC druebergeht.Und genau das stört mich. Weil es IMHO das Exception Konzept aushebelt.
den zusammenhang verstehe ich jetzt nicht. was hat das closen einer connection mit dem exception konzept zu tun.
das du nicht auf alle exceptions reagieren willst ist dein bier.
ich finde checked exceptions gut im architektur sinne und wenn ich das gut plane dann weiss ich auch welche methoden welche exceptions werfen.
man sollte zB in architektur entscheidungen immer schauen das man Basisklassen exceptions wirft um darauf dann spezialisierte exceptions aufzubauen. Ich kann dann die exceptions einfach durchreichen. das sollte mir aber schon von anfang an klar sein.
ich behandle zB fast keine Exceptions in methoden sondern habe meinen eigenen Exception handler der das fuer mich macht.Aber bei DB Verbindungen oder ähnlichen 'seltenen' Resourcen hätte ich eben gerne ne Möglichkeit zu wissen, dass die Resource freigegeben wird.
und diese moeglichkeit hast du
den wenn du .close sagst dann ist die db connection geclosed (das heisst belegt keine resource des servers mehr) und kann vom GC bereinigt werdenHast du da mal so ein 'Horror Beispiel'?
klar hab ich eines
ein bekannter von mir hat eine zeitlang mit mir bei einer firma gearbeitet.
als ich dann dazu kam seinen C++ code zu debuggen musste ich mich erst einmal ein paar stunden in seine gesamt klassenstruktur einarbeiten (ist ja normal) und am naechsten tag habe ich dann mindestens genausoviel zeit damit verbracht zu checken was denn nun A + B intern bedeutet.
das problem auf das ich hinaus will ist das die lesbarkeit absolut 0 ist bei operatorenueberladung fuer jemand der sich neu einarbeitet.
wenn ich bereits erfahrung mit dem system und den operatoren habe dann ist es simpel. ich weiss was was tut und wie was zusammenhaengt. hoffentlich weiss ich was es im hintergrund ca tut. daraufhin ist es schneller im schreiben und auch schneller beim lesen.
Nur darf man halt nicht davon ausgehen das ich immer wen parat habe der sich damit auskennt. legacy systeme und enterprise software kann schon mal 10-15 jahre im betrieb bleiben. und seien wir uns ehrlich. die chance das ncoh wer nach 10 jahren im betrieb ist der sich damit auskennt ist relativ gering. speziell wenn das system von einer externen firma uebernommen wird, die wartung jedoch nach einer einschulung intern gemacht wird.es stimmt wohl das a+b nix anderes als add(a,b) ist
aber was ist add(a,b) fuer 2 objekte ?? was passiert hier?a.add(b) ist einfach das ist ein a+=b (zumindest sollte es sein laut eines alten handbuches das ich nutze)
man sollte naemlich solche operationen immer auch statisch haben
mit Klasse.add(a,b)aber ich muss auch in die doku schauen wenn ich in c++ ein Object1 + Object2 sehe
- zumindest wenn ich wissen will was das ding genau machtich hoffe du siehst was ich meine
gomberl
-
Was du an den Nullpointern schlecht findest, ist mir ein Rätsel. Manchmal braucht man das halt einfach, dass ein Pointer gerade auf nichts zeigt. Und immerhin kann er nicht undefiniert sein, und du kannst überhaupt nicht irgendeinen Muck damit machen. Wenn du es wie eine C++ Referenz benutzen willst, dann kannst du ja die Referenz final machen.
Und wenn du deine Exceptions von RuntimeException ableitest, dann musst du sie nicht in der throws-Listen angeben, dann hast du es so wie in C++.
Macht ja auch manchmal Sinn, sonst würde ja jede Methode eine IndexOutOfBoundsException werfen, wenn du dort mit Arrays arbeitest. Aber in manchen Situationen ist das schon sehr sinnvoll, dass der Compiler darauf aufpasst, dass man jeden Fall behandelt. Safety First.Und evtl. interressieren dich noch:
System.runFinalization(); System.runFinalizersOnExit(true);
@Helium: Das war eindeutig ein Flame-Versuch.
-
@Helium ... komm nicht mit vorurteilen ....
Naja ich kenne RAII wiklich nicht !Nun ich kenne Shade's Argument ist ja auch richtig, bloss ich finde es nicht schlimm, dass das so gelöst würde.
Viel schlimmer was mich an Java nervt ist expliziertes Exceptionshandling, das finde ich in C# besser gelöst, und die Standardmässige public virtual deklarierung von Members - ja ich weiss, dass es so gesagt nicht richtig ist - C# sind Members private, finde ich viel praktischer ...
Also in Endeffekt finde ich viels in C# besser gelöst als in Java... bloss C# und NET sind nicht wirklich Platformunabhängig.
Alles ne Geschmacksache^^
-
puh schon wieder ein beitrag:
da bin ich gerade mit dem anderen fertigDarum geht es doch gerade. Ich will eben nicht selber das machen (und uU es vergessen). Das ist doch das Argument warum ich den GC verwenden soll GC Verfechter sagen: nutze den GC, denn dann kannst du das Freigeben des Speichers nicht vergessen. Nun ist Speicher aber nicht so teuer wie ne DB Verbindung.
im endeffekt wirst du es eh im finalizer stehen haben (das close)
bzw im finalizer der connection klasse ist das close auch drinnenHier helfen dir verschiedene GC algorithmen. du kannst auch den GC regelmaessig aufrufen.
normalerweise reicht der normale GC - oder du benutzt sowieso connection pooling - das optimum in dem bereichja aber in C++ musst du auch daran denken das die verbindung am ende des scopes geschlossen wird. ich bevorzuge es uebrigens dezidiert connections zu schliessen. das erhoeht die lesbarkeit und bringt keine nachteile (IMHO)
gomberl
-
@Helium ... komm nicht mit vorurteilen ....
Naja ich kenne RAII wiklich nicht !RAII ist in Java nicht Möglich, in C++ und D jedoch schon und dort auch sehr beliebt.
es ist garantiert das finalize aufgerufen wird. das wird es immer. allerdings ist nicht garantiert WANN finalize aufgerufen wird, weil es eben vom GC aufgerufen wird bevor das objekt verworfen wird.
Ja und es läuft in 'nem ganz anderen Thread, weshalb man auchnoch auf Synchoronisierung achten muss.
und diese moeglichkeit hast du
den wenn du .close sagst dann ist die db connection geclosed (das heisst belegt keine resource des servers mehr) und kann vom GC bereinigt werdenNein hast du nicht. Du kannst es vergessen bzw. in einer komplexen Situation eine Möglichkeit übersehen. In C++ unmöglich.
-
Ja und es läuft in 'nem ganz anderen Thread, weshalb man auchnoch auf Synchoronisierung achten muss.
Nein synchronisierung ist kein thema bei der GC. Das ding ist kein simpler GC wie er damals in COM (reference counting) verwendet wurde.
ich empfehle hierfeur java.sun.com und auch www.javaworld.comZitat:
und diese moeglichkeit hast du
den wenn du .close sagst dann ist die db connection geclosed (das heisst belegt keine resource des servers mehr) und kann vom GC bereinigt werdenUnmoeglich??
Ich kann auch in C++ vergessen ein free auf ein objekt zu machen.
Kommt nur darauf an ob ich objekte am heap oder stack anlege.
Das Argument kommt bei mir nicht durch. Ich habe schon selbst genug memory leaks in C++ programmiertgomberl
-
Helium schrieb:
und diese moeglichkeit hast du
den wenn du .close sagst dann ist die db connection geclosed (das heisst belegt keine resource des servers mehr) und kann vom GC bereinigt werdenNein hast du nicht. Du kannst es vergessen bzw. in einer komplexen Situation eine Möglichkeit übersehen. In C++ unmöglich.
Ok. In C++ kanst du dafür "delete" vergessen. Der Vorteil an Java ist, dass solche Fehler i.d.R. nicht gleich zu einer Katastrophe führen. Für soetwas gibt es die finalizer. Die sind in so einem Zusammenhang als "Sicherungsmethode" gedacht. Wenn der Programmierer den oben beschriebenen Fehler macht, dann kommt trotzdem i.d.R. nach einiger Zeit der GC, der den finalizer aufruft, in dem dann die entsprechende Abschlussmethode nochmal aufgerufen wird.
(...wie gesagt, das ist nur eine "Sicherung" und soll hier keine Aufforderung sein, die Abschlussmethoden nicht zu nutzen.)
-
ich meinte auch delete
in welcher sprache war es denn "free" .. hmmm
na egal
-
Der GC läuft och in einem eigenen Thread und führt die Finalisierung in seinem Thread aus, oder sehe ich das falsch?
Kommt nur darauf an ob ich objekte am heap oder stack anlege.
Das Argument kommt bei mir nicht durch. Ich habe schon selbst genug memory leaks in C++ programmiertWenn du etwas auf dem Heap anlegst lässt du es einfach von etwas auf dem Stack liegenden verwalten. (Smart-Pointer, ...). Wenn du das nicht tust bist du es selbst schuld.
Wir reden gerade nicht nur über Speicher (wofür ein GC natürlich ganz große Klasse ist!), sondern eben über Dinge, wie Datenbakverbindungen.Niemand sagt, das du nicht trotzdem eine close-Methode implementieren darfst, um vorzeitig zu schließen. Aber C++ sorgt eben dafür, dass spätestens, wenn der Scope verlassen wird das Ding zu ist (auch im Fall eine Exception). In Java muss ich explizit finally-Bereiche schreiben. Das ist doch einfach nur lästig.
-
Zeus schrieb:
Viel schlimmer was mich an Java nervt ist [...] die Standardmässige public virtual deklarierung von Members - ja ich weiss, dass es so gesagt nicht richtig ist
Du sagst es ja selbst. Das, was du da sagst, ist nicht richtig. Wie kann es dich dann an Java stören. Standardmäßig ist in Java nichts public, sondern alles packageprivate. Der Sichtbarkeitsbereich ist auf das Paket eingeschränkt, in dem sich die Klasse befindet.
Das mit "virtual vs. final" ist wohl Geschmackssache. Ob man jetzt markiert, dass etwas überschrieben werden kann oder ob etwas nicht überschrieben werden kann ist IMHO egal. Man muss sich in jedem Fall Gedanken darüber machen, ob man das Überschreiben zuläßt oder nicht.
-
Shade Of Mine schrieb:
Socket sock=null; try { sock=new Socket(); } catch(...) { ... } finally { try { if(foo) foo.close(); } catch(HabIchVergessenException) { } }
Bei sowas frage ich mich: warum keine Destruktoren? Und warum wirft der 'Dtor'? Ich kann meistens dann sowieso nix machen. Höchstens den Fehler loggen...
Mal gucken, in welchem Fall beim Schließen des Sockets eine Exception geworfen wird...
Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.
Wie sollte das denn sonst gelöst werden? Einfach den Socket schließen und die Threads, um die es da geht, auf etwas "ungültiges" zugreifen lassen? Das kann ja wohl nicht die Lösung sein. So eine Exception muss man einfach schmeißen und behandeln.
-
Wobei mir das final schon lieber ist. Weil final kann ich vergessen, wenn ich virtual vergesse, hab ich evtl. nen hard-to-find-bug. Außerdem verbietet ja niemand der VM, für Aufrufe an nicht-redefinierte Methoden, ne feste Aufrufaddresse zu verwenden.
Was mich an Java stört, ist das gammelige protected, was halt überhaupt nichts protected, sondern noch öffentlicher wie das package-private ist. Das find ich mal wirklich schlecht.
-
Wenn du etwas auf dem Heap anlegst lässt du es einfach von etwas auf dem Stack liegenden verwalten. (Smart-Pointer, ...). Wenn du das nicht tust bist du es selbst schuld.
Wir reden gerade nicht nur über Speicher (wofür ein GC natürlich ganz große Klasse ist!), sondern eben über Dinge, wie Datenbakverbindungen.Alles liegt im speicher.
Datenbankverbindungen auch.Mir geht es um das triggering des destructors.
und der ist AFAIK getriggered wenn der scope verlassen wird oder wenn ich ein delete mache.
das heisst mache ich kein delete auf etwas das am heap erzeugt wurde so habe ich ein memory leak und eine nicht schliessende verbindung. punktum. und das ist moeglich in C++, ganz einfach. WIE ich jetzt gegen sowas vorbeugen kann war nicht gegenstand der diskussion.
ich habe auf den satz "In C++ unmöglich" geantwortet, weil er nonsens ist.wobei ich sagen muss das ich schon sehr aus der C++ programmierung heraussen bin.
-
Optimizer schrieb:
Was mich an Java stört, ist das gammelige protected, was halt überhaupt nichts protected, sondern noch öffentlicher wie das package-private ist. Das find ich mal wirklich schlecht.
ja das find ich auch sehr verwirrend - da ham sich die sprachen designer ausgezeichnet
-
Ich glaube die Diskussion über Destruktoren sollten wir bleiben lassen...
@gomberl:
Ich verstehe nur immer noch nicht, warum ein
a.add(b); bzw.
x=Foo.add(a,b);
besser ist als
a+=b; bzw.
x=a+b;Ich weiss bei einem add() genausowenig über die Aktion wie bei einem operator+
-
Das Destruktor-Konzept würde für Java einfach keinen Sinn machen, weil man dann vorschreiben müsste, wann ein Destruktor aufgerufen wird.
Wenn sich ein Programmierer dann acuh sowas verlässt, kümmert er sich indirekt schon wieder um die Speicherverwaltung und die soll ja in Java automatisch stattfinden.
Man soll sich um nichts kümmern müssen, das ist einfach eine andere Philosophie. Man überlässt die Speicherverwaltung komplett der VM, die das sowieso viel besser macht, als man es von Hand coden würde.
Daraus ergeben sich auch ein paar Nachteile, da hat Shade nicht ganz unrecht. Aber in C++ ist es IMO trotzdem leichter, ganz allgemein ein paar Sachen zu vergessen, in Java muss man sich nicht um so viel kümmern.Operatoren: Ich vermisse Operator-Überladung in Java auch. Es ist theoretisch nicht notwändig und auch gerade aufgrund der Referenz-Semantik ein bisschen problematisch bei == und !=. Da finde ich den Graben zwischen == und equals() schon gut, den sollte man auch nicht ändern können.
Aber ein + und - überladen, wär schon was feines manchmal.
-
gomberl schrieb:
Alles liegt im speicher.
Datenbankverbindungen auch.Aber der Unterschied zwischen Speicher und DB Verbindung ist dir klar?
Das eine ist ne kritische Resource (DB) das andere eine Resource die nahezu unendlich vorhanden ist.Mir geht es um das triggering des destructors.
und der ist AFAIK getriggered wenn der scope verlassen wird oder wenn ich ein delete mache.
das heisst mache ich kein delete auf etwas das am heap erzeugt wurde so habe ich ein memory leak und eine nicht schliessende verbindung. punktum. und das ist moeglich in C++, ganz einfach. WIE ich jetzt gegen sowas vorbeugen kann war nicht gegenstand der diskussion.Doch.
C++ bringt nunmal wenig in die Sprache integrierte 'Features' mit.
Nur aus diesen Features lassen sich eben Sachen basteln: wie zB das RAII Idiom.
Und deshalb gibt es in einem guten C++ Programm keine Resource Leaks - weil eben alles über Destruktoren zerstört wird (auch dynamisch allokierter Speicher).Das man auch die Möglichkeit hat, dieses Feature nicht zu nutzen ist doch kein Nachteil der Sprache.
-
shade: in dem fall weisst du genausoviel da hast du recht
die (vom mir bereits erfahrene problematik) liegt darin das das einlesen laenger dauert - bzw man fehler leichter uebersieht.IMHO. IME (in my experience)ich finde einfach das methodenaufrufe besser lesbar sind und man sich auch mehr darunter vorstellen kann (speziell wenn die namen gut gewaehlt sind)
bei add und + ist kein unterschied (das sagt beides nicht viel wenn die objekte nicht gerade irgendwelche mathematischen oder graphischen dinge sind)
ich persoenlich habe das operator ueberladen sehr gerne genutzt bis zu dieser erfahrung.
seither benutze ich es nicht mehr. methodenaufrufe sind genausogutmeine meinung
gomberl
-
a = (b + c) * (d + e);
a.assign(b.add(c).mul(d.add(e));
LOL
-
Aber der Unterschied zwischen Speicher und DB Verbindung ist dir klar?
Das eine ist ne kritische Resource (DB) das andere eine Resource die nahezu unendlich vorhanden ist.das ist mir schon klar.
Ich weiss auch auf was du hinaus willst, aber das aendert meine ansicht nicht das ein .close() benutzt werden sollte.
eine kritische resource gehoert dezidiert geoeffnet und dezidiert geschlossen. IMHO.C++ bringt nunmal wenig in die Sprache integrierte 'Features' mit.
Nur aus diesen Features lassen sich eben Sachen basteln: wie zB das RAII Idiom.
Und deshalb gibt es in einem guten C++ Programm keine Resource Leaks - weil eben alles über Destruktoren zerstört wird (auch dynamisch allokierter Speicher).Das man auch die Möglichkeit hat, dieses Feature nicht zu nutzen ist doch kein Nachteil der Sprache.
ueber RAII hab ich 2 mal gelesen in meinem leben, dementsprechend kann ich nix dazu sagen.
ich will hier auch C++ nicht schlecht machen.
Ich weiss auch das es in einem guten C++ prorgramm keine resource leaks gibt, habe auch schon so etwas geschrieben, man glaubt es kaum.Frage: wieviele "gute" C++ programme kennst du. Ich sage gerade 20 prozent sind gut geschrieben, weil eben sehr viel zeitdruck auf den personen lastet und man nicht alles machen kann. man hat auch organisatorische aufgaben und dann kommen noch altlasten hinzu.
Fuer alles weiter koennen wir einen thread ueber software quality management aufmachen. Auch verweise ich auf den Chaos Report. Jedes jahre wieder eine freude zu sehen wieviele IT projekte in die hose gehen.Das man auch die Möglichkeit hat, dieses Feature nicht zu nutzen ist doch kein Nachteil der Sprache.
das hab ich auch nie behauptet. ich habe nur behauptet das "C++ nicht die eierlegende wollmilchsau ist" -> "In C++ unmoeglich"
In C++ ist viel mehr moeglich. auf der positiven wie auch auf der negativen seite. Und das ist auch gut so.