mikrocontroller.net

Forum: PC-Programmierung Java-Quizfrage


Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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!

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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!

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...)

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stephan M. (stephanm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das da gibt zunächst 0 aus, danach 42.
public class Quiz {

  private static final class DeepThought extends Supercomputer {
    
    int whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything() {
      return theAnswer;
    }
    
    private int theAnswer = 42;
  }
  
  private static abstract class Supercomputer {
    
    public Supercomputer() {
      int theAnswer = whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
      System.out.println(theAnswer);
    }
    
    abstract int whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
  }

  
  public static void main(String[] args) {
    
    DeepThought deepThought = new DeepThought();
    
    int theAnswer = deepThought.whatIsTheAnswerToTheUltimateQuestionOfLifeTheUniverseAndEverything();
    System.out.println(theAnswer);
  }
  
}

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens gibt es hier unterhaltsamere Rätsel präsentiert von Joshua 
Bloch höchstpersönlich.

http://video.google.com/videoplay?docid=9214177555401838409#

Autor: Stephan M. (stephanm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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&th...

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

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na dann. Ist zwar kein Java, sondern Standard-C, aber trotzdem schön:
printf("%i", abs(INT_MIN));
/* Ausgabe: -2147483647 (negativ!) */

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


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

Über letzteres bin ich auch schon böse gestolpert.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
klaus@a64a:~ > gcc -Wall t.c
t.c: In function ‘main’:
t.c:11: warning: comparison of distinct pointer types lacks a cast
t.c:12: warning: comparison of distinct pointer types lacks a cast
klaus@a64a:~ > ./a.out
1. ungleich
2. gleich

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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ß!

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
>
> klaus@a64a:~ > gcc -Wall t.c
> t.c: In function ‘main’:
> t.c:11: warning: comparison of distinct pointer types lacks a cast
> t.c:12: warning: comparison of distinct pointer types lacks a cast
> klaus@a64a:~ > ./a.out
> 1. ungleich
> 2. gleich
> 

Ich schäme mich, hab ich doch glatt vertauscht... G

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Claudio Du irrst:

http://java.sun.com/docs/books/jls/third_edition/h...

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):
public class Hamlet {

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

}

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.

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und ein C-Puzzler hinterher:
#include "stdio.h"
#define  e 3
#define  g (e/e)
#define  h ((g+e)/2)
#define  f (e-g-h)
#define  j (e*e-g)
#define k (j-h)
#define  l(x) tab2[x]/h
#define  m(n,a) ((n&(a))==(a))

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

main(m1,s) char *s; {
    int a,q,c,d,o[k],n=(int)s;
    if(m1==1){ char q[2*j+f-g]; main(l(h+e)+h+e,q); printf(q); }
    else switch(m1-=h){
  case f:
      a=(q=(c=(d=g)<<g)<<g)<<g;
      return(m(n,a|c)|m(n,q)|m(n,a|d)|m(n,c|d));
  case h:
      for(a=f;a<j;++a)if(tab1[a]&&!(tab1[a]%((long)l(n))))return(a);
  case g:
      if(n<h)return(g);
      if(n<j){n-=g;c='D';o[f]=h;o[g]=f;}
      else{c='\r'-'\b';n-=j-g;o[f]=o[g]=g;}
      if((q=n)>=e)for(q=g<<g;q<n;++q)o[q]=o[q-h]+o[q-g]+c;
      return(o[q-g]%n+k-h);
  default:
      if(m1-=e) main(m1-g+e+h,s+g); else *(s+g)=f;
      for(*s=a=f;a<e;) *s=(*s<<e)|main(h+a++,(char *)m1);
  }
}

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

mfg, Stefan.

Autor: Robert S. (razer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 :)

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau wegen dem "Kenn ich schon"  ist das langweilig. :-P

Autor: Stephan M. (stephanm)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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&f...

Das hat mich deutlich mehr erstaunt als diese ewigen Versuche, "hello, 
world!" möglichst kompliziert hinzuschreiben...

Stephan

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stefan May (smay4finger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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.

Autor: Claudio H. (bastelfinger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die genaue Exception weiss ich nicht mehr, war aber vielleicht eine 
NullPointerException.

Autor: Filter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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 :)

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: Filter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.