Java-Quizfrage

OP #1586230
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!
Persönliche Seite
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)
OP
>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!
Persönliche Seite
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...)
OP
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
Gast
Das da gibt zunächst 0 aus, danach 42.
1
public class Quiz {
2

3
  private static final class DeepThought extends Supercomputer {
4
    
5
    int whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything() {
6
      return theAnswer;
7
    }
8
    
9
    private int theAnswer = 42;
10
  }
11
  
12
  private static abstract class Supercomputer {
13
    
14
    public Supercomputer() {
15
      int theAnswer = whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
16
      System.out.println(theAnswer);
17
    }
18
    
19
    abstract int whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
20
  }
21

22
  
23
  public static void main(String[] args) {
24
    
25
    DeepThought deepThought = new DeepThought();
26
    
27
    int theAnswer = deepThought.whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
28
    System.out.println(theAnswer);
29
  }
30
  
31
}
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
Persönliche Seite
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
Gast
Na dann. Ist zwar kein Java, sondern Standard-C, aber trotzdem schön:
1
printf("%i", abs(INT_MIN));
2
/* Ausgabe: -2147483647 (negativ!) */
3

4
int *a;
5
int b[10];
6
puts( (a == &a) ? "1. gleich" : "1. ungleich" );
7
puts( (b == &b) ? "2. gleich" : "2. ungleich" );
8

9

10
/* Ausgabe: 1. gleich 2. ungleich */

Über letzteres bin ich auch schon böse gestolpert.
1
klaus@a64a:~ > gcc -Wall t.c
2
t.c: In function ‘main’:
3
t.c:11: warning: comparison of distinct pointer types lacks a cast
4
t.c:12: warning: comparison of distinct pointer types lacks a cast
5
klaus@a64a:~ > ./a.out
6
1. ungleich
7
2. gleich
Gast
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.
OP
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?
Gast
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.
OP
>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ß!
Gast
Klaus Wachtler schrieb:
>
1
> klaus@a64a:~ > gcc -Wall t.c
2
> t.c: In function ‘main’:
3
> t.c:11: warning: comparison of distinct pointer types lacks a cast
4
> t.c:12: warning: comparison of distinct pointer types lacks a cast
5
> klaus@a64a:~ > ./a.out
6
> 1. ungleich
7
> 2. gleich
8
>

Ich schäme mich, hab ich doch glatt vertauscht... G
Gast
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):
1
public class Hamlet {
2

3
  public static void main(String[] args) {
4
    Random rnd = new Random();
5
    boolean toBe = rnd.nextBoolean();
6
    Number result = (toBe || !toBe) ? new Integer(3) : new Float(1);
7
    
8
    System.out.println(result);
9
  }
10

11
}

Was wird auf System.out ausgegeben?

 a) 3
 b) 1.0
 c) wirft eine Exception
 d) etwas total anderes

Hint: JLS §15.25

mfg, Stefan.
Gast
Und ein C-Puzzler hinterher:
1
#include "stdio.h"
2
#define  e 3
3
#define  g (e/e)
4
#define  h ((g+e)/2)
5
#define  f (e-g-h)
6
#define  j (e*e-g)
7
#define k (j-h)
8
#define  l(x) tab2[x]/h
9
#define  m(n,a) ((n&(a))==(a))
10

11
long tab1[]={ 989L,5L,26L,0L,88319L,123L,0L,9367L };
12
int tab2[]={ 4,6,10,14,22,26,34,38,46,58,62,74,82,86 };
13

14
main(m1,s) char *s; {
15
    int a,q,c,d,o[k],n=(int)s;
16
    if(m1==1){ char q[2*j+f-g]; main(l(h+e)+h+e,q); printf(q); }
17
    else switch(m1-=h){
18
  case f:
19
      a=(q=(c=(d=g)<<g)<<g)<<g;
20
      return(m(n,a|c)|m(n,q)|m(n,a|d)|m(n,c|d));
21
  case h:
22
      for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
23
  case g:
24
      if(n<h)return(g);
25
      if(n<j){n-=g;c='D';o[f]=h;o[g]=f;}
26
      else{c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
27
      if((q=n)>=e)for(q=g<<g;q<n;++q)o[q]=o[q-h]+o[q-g]+c;
28
      return(o[q-g]%n+k-h);
29
  default:
30
      if(m1-=e) main(m1-g+e+h,s+g); else *(s+g)=f;
31
      for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
32
  }
33
}

Was gibt das Program aus? Achtung, ebenfalls geklaut und leicht 
abgeändert, wegen Forum-Spamfilter.

mfg, Stefan.
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
OP
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.
Gast
> 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.
Gast
>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 :)
Persönliche Seite
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...
Gast
>> 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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 16 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.