Weil ich diesen Samstag arbeiten muss, hier eine kleine Quizfrage um
euch zu quälen:
Kennt ihr einen Weg, wie man in Java auf uninitialisierte Attribute
eines Objekts zugreifen kann? Bitte den Quellcode dazu posten. Ich kenne
einen Weg, die Auflösung gibt es später.
Bitte kein google benutzen, sondern auf eigene Lösungen kommen!
Alle Attribute werden per default inistialisiert (mit null oder je nach
primitivem Typ vorgegebenem default).
Uninitialisierte (lokale) Variablen gehen nicht durch den Compiler...
also wenn dann bitte ein Beispiel.
Oder meinst du das die Variablen den von dir vorgegeben (initial) Wert
zum Zeitpunkt des Zugriffs noch nicht haben?
Das Phnomen hatte ich auch schon das ein oder andere mal, trotzdem sind
die Variablen initialisiert (nur nicht mit dem Wert welchen man zunächst
erwartet)
>Alle Attribute werden per default initialisiert (mit null oder je nach>primitivem Typ vorgegebenem default).
Genau das meine ich, es gibt trotzdem eine Möglichkeit, VOR dieser
Initialisierung auf ein Attribut zuzugreifen. Viel Spaß beim Nachdenken!
Claudio H. schrieb:
>>Alle Attribute werden per default initialisiert (mit null oder je nach>>primitivem Typ vorgegebenem default).>> Genau das meine ich, es gibt trotzdem eine Möglichkeit, VOR dieser> Initialisierung auf ein Attribut zuzugreifen. Viel Spaß beim Nachdenken!
Und dann? Wie merkst du das dieser Zugriff wirklich unitilalisiert
geschieht?
Und was soll das überhaupt bringen? (Wenn es nicht sogar von der VM
Implementierung abhängig ist...)
Hey, das ganze ist eine Quizfrage, muss also keinen Nutzen haben. Man
kann aber durch Zuweisung an eine Variable, die anschließend erst
initialisiert wird, schöne Fehler einbauen. Also sollte man das schon im
Hinterkopf behalten.
Aber eine Zuweisung welche danach überschrieben wird ist doch kein
Zugriff auf eine uninitialisierte Variable, daher ja meine Frage wie du
erkennst das du auf eine uninitialisierte Variable zugreifst...
Naja, du weisst ja, dass Java eine Reihenfolge der Initialisierung
vorgibt, z.B. zunächst die static Attribute, dann der static Block, dann
die Instanzattribute, dann werden die Konstruktoren aufgerufen, am
Anfang jedes Konstruktors der super-Konstruktor usw.
Kannst du dich irgendwie in diese Reihenfolge reinhängen, und auf ein
Attribut zugreifen, welches erst später initialisiert wird? Per meiner
Definition ist dieser Zugriff dann uninitialisiert.
Claudio H. schrieb:
> Kennt ihr einen Weg, wie man in Java auf uninitialisierte Attribute> eines Objekts zugreifen kann?
Per JNI, wenn man die "Lücke" zwischen AllocObject und
CallNonvirtualVoidMethod ausnutzt. Was die JRE dazu sagt weiß ich zwar
nicht, aber den Zugriff auf uninitialisierte Felder kann ich da bequem
explizit hinschreiben ;-)
Stephan
Stefan May schrieb:
> Das da gibt zunächst 0 aus, danach 42.
Claudio H. (Threadersteller) schrieb:
> Weil ich diesen Samstag arbeiten muss
Lass mich raten: Claudio musste nur deswegen Samstag arbeiten, weil ein
durch ein derartiges Konstrukt entstandener Fehler dringend bereinigt
werden musste...
Hier findet man ein bisschen Diskussion zum Verhalten von Java und von
anderen Programmiersprachen in diesem Fall (der dritte Beitrag von oben
erklärt das Verhalten des Codes von Stefan):
http://www.artima.com/forums/flat.jsp?forum=226&thread=113723
Ich persönlich finde übrigens das Verhalten von C++ besser, auch
deswegen, weil ich es selbst erleben musste, dass das hier ausgenutzte
Verhalten von Java zu schwer zu lokalisierenden, ekligen Fehlern führen
kann. Gelegentlich findet man daher die Regel, dass Konstruktoren nur
als "final" gekennzeichnete Methoden der eigenen Klasse aufrufen dürfen.
Stephan
Läubi .. schrieb:
> Oder meinst du das die Variablen den von dir vorgegeben (initial) Wert> zum Zeitpunkt des Zugriffs noch nicht haben?
Hatte ich doch oben schon geschrieben... Dieser Zugriff ist aber eben
nicht uninitialisiert, sonder du bekommst (korrekterweise) 0 zurück, das
dies nicht deinem erwarteten Wert (42) entspricht ist doch wieder etwas
anderes.
Das Objekt oder die Variable wird schon initialisiert, nur dein davon
abweichender Default wert wird erst zugewiesen wenn der Konstruktor
durchlaufen wurde. Das ist ärgerlich wenn man es weiss aber durchaus ein
vorhersehbares Verhalten.
@Stephan M.
Naja das Problem tritt nur auf wenn man mehrere Aufgaben im Kontruktor
ausführt, was ich mittlerweile für mich persönlich als schlechten Stil
deklariert habe
Läubi Du hast natürlich recht, daß das kein Zugriff auf uninitialisierte
Variablen ist. Der TO hat ja seine Definition von "uninitialisiert"
wiedergegeben.
Und zu C++: Sowohl in Java als auch in C++ gibt es böse Fallen, die sich
nur durch "Best Practices" umschiffen lassen. Nicht umsonst gibt es zu
diesem Thema sowohl für C++ als auch Java diverse Bücher, die man
gelesen haben sollte.
mfg, Stefan.
Smayfinger, du hast "meine" Lösung gefunden. Ich bin tatsächlich mal
über dieses Verhalten gestolpert, auf meinem Entwicklungsrechner lief
das wunderbar, der ContinuousIntegration Server hatte eine andere VM und
ist abgestürzt.
Das Problem in meinem Fall war ein Framework, welches massiv auf dem
"Template Method" Pattern aufgebaut hat, und mich dadurch zu diesem
Ansatz gezwungen hat.
Hat noch jemand eine Quizfrage?
Dieses Verhalten ist ganz klar definiert und ist ganz sicher "bad
practice".
> Hat noch jemand eine Quizfrage?
Ja, ein ganzes Buch voll. Siehe Link zum Vortrag von Joshua Bloch.
>Dieses Verhalten ist ganz klar definiert und ist ganz sicher "bad
practice".
Wenn man allerdings den Attributen nicht im Konstruktor, sondern inline
einen Wert zuweist, dann ist das Verhalten von VM zu VM unterschiedlich.
Also glaube ich nicht, dass das SO genau definiert ist.
Dass es Bücher mit Quiz-Fragen gibt, ist mir schon klar, nur macht das
Rätseln im Forum mehr Spaß!
Claudio Du irrst:
http://java.sun.com/docs/books/jls/third_edition/html/execution.html#44670
In Punkt 4 geht es um die Initialisierung der Instanz-Variablen. In
§12.5 steht am Ende auch die Antwort auf Deine Quiz-Frage.
Mich würde interessieren, mit welchen VMs Du das unterschiedliche
Verhalten beobachtet hast.
Und noch ein Puzzler hinterher (Achtung ist geklaut und nicht von mir):
Stefan May schrieb:
> Was wird auf System.out ausgegeben?>> a) 3> b) 1.0> c) wirft eine Exception> d) etwas total anderes
d) nämlich 3.0
Kenn ich schon :)
Stefan May schrieb:
> Und ein C-Puzzler hinterher:
Jeder, der mal die Programme beim Obfuscated Perl Contest gesehen (oder
gar zu verstehen versucht) hat, wird sowas NIE NIE NIE durch den
Compiler jagen und dann ausführen, weil es umgefähr eine Bazillion
Möglichkeiten gibt, ein 'system("rm -fr $HOME")' zu verstecken 8-)
Andererseits scheinen Compiler langsam aber sicher einzuholen, vgl. das
Posting "danni - Apr 05, 2008 - 02:36 PM" / "Post subject: RE: Re: RE:
operand out of range" auf
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=61771&start=0
Das hat mich deutlich mehr erstaunt als diese ewigen Versuche, "hello,
world!" möglichst kompliziert hinzuschreiben...
Stephan
smayfinger,
die JDKs waren Version 1.4.1, beide auf WindowsXP. Wenn man in der
überschriebenen abstrakten Methode Werte an Attribute zugewiesen hat,
gab es zur Laufzeit bei einem JDK eine Excpetion, das andere lief durch.
Kann natürlich auch am Compiler gelegen haben.
> gab es zur Laufzeit bei einem JDK eine Excpetion
Welche Exception war das genau?
In Java 1.4 und älter waren einige Patterns gebräuchlich, die nicht
funktionierten. Zum Beispiel das double-checked-locking. In Java 1.5
wurde daraufhin das Memory-Model gründlich poliert und klar definiert.
In 1.4 war das Verhalten tatsächlich abhängig vom verwendeten Compiler
und von der verwendeten JVM.
Von Angelika Langer gibt es einen netten Vortrag zum Java Memory Model,
welcher wirklich sehenswert ist.
mfg, Stefan.
>die JDKs waren Version 1.4.1, beide auf WindowsXP. Wenn man in der>überschriebenen abstrakten Methode Werte an Attribute zugewiesen hat,>gab es zur Laufzeit bei einem JDK eine Excpetion, das andere lief durch.>Kann natürlich auch am Compiler gelegen haben.
ich finde es lüstig wie die von Java gepriesene
"Plattformunabhängigkeit"
von der Wirklichkeit eingeholt wird :)
Filter schrieb:
>>die JDKs waren Version 1.4.1, beide auf WindowsXP. Wenn man in der>>überschriebenen abstrakten Methode Werte an Attribute zugewiesen hat,>>gab es zur Laufzeit bei einem JDK eine Excpetion, das andere lief durch.>>Kann natürlich auch am Compiler gelegen haben.>> ich finde es lüstig wie die von Java gepriesene> "Plattformunabhängigkeit"> von der Wirklichkeit eingeholt wird :)
Ich finde es lustig wie Leute ohne Fundierte Kenntnisse sich über
scheinbare Makel andere Leute Arbeit amüsieren...
Was hat bitte ein (möglicherweise) unterschiedliches Verhalten
verschiedener JavaVM (IBM? Windows? Sun?) mit Plattformunabhänigkeit zu
tun? Zumal beide auf WinXP liefen...
Zumal noch nicht mal der genaue Fehler reproduziert werden könnte, da
Source + genauere Umgebung nicht (mehr) zur Verfügung stehen...
>> ich finde es lüstig wie die von Java gepriesene>> "Plattformunabhängigkeit">> von der Wirklichkeit eingeholt wird :)>Ich finde es lustig wie Leute ohne Fundierte Kenntnisse sich über>scheinbare Makel andere Leute Arbeit amüsieren...
nett, dass du ohne mich zu kennen, als jemand ohne "fundierte
Kenntnisse"
(und dann noch falsch geschrieben, bin heute mal so kleinlich :)
hinstellst.
nein, ich vertrete die Meinung, dass eine komplexe Sache auch dann
komplex bleibt, wenn man ihr ein anderes Pelz überstopft.