Kann man in Java undefiniertes Verhalten erzeugen??



  • Oder führt in Java alles zu definiertem Verhalten?



  • AFAIK ist bei manchen APIs undefiniertes Verhalten dokumentiert.
    Mit den Sprachmitteln selber ist das IMHO nicht möglich.



  • Das kommt drauf an, was du unter undefiniertem Verhalten verstehst...

    Ein beispiel, das oft als 'undefiniertes Verhalten' bezeichnet wird ist sehrt leicht zu erzeugen, indem man einfach mit mehreren Threads lesend/schreibend unsynchronisiert auf ein Objekt zugreift.



  • ich bin mir unsicher, ob dieses beispiel hier als undefiniertes verhalten interpretiert werden kann.
    aber es wird eine methode aufgerufen, bevor das objekt fertig initialisiert ist.
    ok, vielleicht ist die sicherheit, daß "0" rauskommt, also int x als 0 erscheint. hmm aber wie wäre das gleiche bei komplizierteren membervariablen..

    class Basis{
        public Basis (){
            methode();
        }
        void methode(){
            System.out.println("Basis");
        }
    }
    class Abgeleitet extends Basis{
    	int x;
    
        void methode(){
            System.out.println("Abgeleitet"+ this.x);
    
        }
    
        Abgeleitet(){
    		this.x=10;
    	}
        public static void main( String [] args){
            new Abgeleitet();
        }
    }
    

    ps: ich weiß, daß man möglichst keine in der kindklasse definierte methode im konstruktor der basis aufrufen sollte. ist nur ein beispiel 😉



  • elise schrieb:

    ok, vielleicht ist die sicherheit, daß "0" rauskommt, also int x als 0 erscheint. hmm aber wie wäre das gleiche bei komplizierteren membervariablen..

    Naja, das wär dann wohl eine Referenz, die mit null initialisiert wird. Alles sauber definiert. Ich bin mir BTW ziemlich sicher, dass das Thread-Beispiel auch definiertes, nur eben kein deterministisches Verhalten hat.

    ps: ich weiß, daß man keine in der kindklasse definierte methode im konstruktor der basis aufrufen darf. ist nur ein beispiel 😉

    Hey, genau um sowas gehts doch. In C++ bedeutet "ich darf nicht" in vielen Fällen UB. In Java fliegt eine Exception ➡ definiertes Verhalten.



  • ok, thanks, ditte war meine frage 🙂

    also geklärt.. und java wieder einen minischritt genähert.



  • ein anderes beispiel wäre jedoch noch, daß ich mal ein programm mit bällen hatte, das thread basiert war.

    nach beenden des programms liefen die noch existierenden bälle weiter über den desktop, da ich sie nicht mit zerstört hatte (vielleicht ähnlich, wie destructors meinung..), sprich: im close kein interrupt aufgerufen.

    wäre zu überlegen, ob das als "undefiniertes verhalten" geltend gemacht werden kann, oder ob die winapi da 'versagt' hat.



  • Kannst du das etwas genauer ausführen? Wenn sich immer noch Bälle bewegt haben, muss doch irgendwie noch mindestens ein Thread gelaufen sein. Damit ist das Programm also nicht beendet.



  • Hi

    @elise: ich vermut mal das die vm im hintergrund noch weiterliev und daher die bälle noch rumgesprungen sind.

    Hatte so änliche fenomene. Programm gestartet auf COM1 Datenverschickt und gelesen. Programm beendet. ( kein symbol mehr in der systemleiste) Programm nocheinmal gestartet und bäng "Can not open COM1." im Taskmanager nachgeschaut, liefen da doch 2 java prozesse. ( grrrr woher wohl der 2. war )

    und dein beispiel scheint sich meiner meinung nach richtig zu verhalten auch wenn das so nicht gewollt ist. Der Constructor von Ableitung ruft vor der eigenen ausführung den Constructor von Basis auf. Der Aufruf von Methode scheint ja auch ok zu sein. Nur das problem ist, das java alle Methoden viruell macht(auser man beendet die virtualisirung von hand). und somit die implementierung der Ableitung aufruft und nicht die der Basis; was ja dei der implementierung von basis ja vorgesehen war.

    Gruss Termite



  • Termite_ schrieb:

    und dein beispiel scheint sich meiner meinung nach richtig zu verhalten auch wenn das so nicht gewollt ist. Der Constructor von Ableitung ruft vor der eigenen ausführung den Constructor von Basis auf. Der Aufruf von Methode scheint ja auch ok zu sein. Nur das problem ist, das java alle Methoden viruell macht(auser man beendet die virtualisirung von hand). und somit die implementierung der Ableitung aufruft und nicht die der Basis; was ja dei der implementierung von basis ja vorgesehen war.

    FYI, in C++ wird in diesem Fall die Methode der Basisklasse aufgerufen, auch wenn sie virtuell ist. So ist es eigentlich auch richtig, weil die Invariante der abgeleiteten Klasse zu dem Zeitpunkt noch nicht eingerichtet wurde. Keine Ahnung, was Sun sich da gedacht hat.



  • Programm beendet. ( kein symbol mehr in der systemleiste)

    Seit wann heißt "kein Symbol mehr in der Taskleiste" das selbe wie "Programm beendet" ? 🙄
    Ein Programm ist genau dann beendet, wenn der Prozess beendet ist und das ist dann der Fall, wenn alle Threads beendet sind.



  • Bashar schrieb:

    FYI, in C++ wird in diesem Fall die Methode der Basisklasse aufgerufen, auch wenn sie virtuell ist. So ist es eigentlich auch richtig, weil die Invariante der abgeleiteten Klasse zu dem Zeitpunkt noch nicht eingerichtet wurde. Keine Ahnung, was Sun sich da gedacht hat.

    Ist das in Java tatsächlich so? Auf jeden Fall kann man das dann umgehen, in dem man die Methode für den Konstruktor private macht. Private Methoden werden nicht dynamisch gebunden.

    Vielleicht macht das sogar Sinn. Könnte ja wirklich sein, dass eine Methode resetMe() bei einem abgeleiteten Objekt etwas anderes machen soll, auch im Konstruktor-Code schon. Wenn die Methode mehr oder weniger öffentlich ist, ist dynamisches Binden vielleicht gewünscht.
    Darüber muss ich aber erst noch mal nachdenken.



  • Optimizer schrieb:

    Private Methoden werden nicht dynamisch gebunden.

    Auch etwas, wo ich mich frage, was sie sich dabei gedacht haben. Ich sag nur Template Method ...

    Vielleicht macht das sogar Sinn. Könnte ja wirklich sein, dass eine Methode resetMe() bei einem abgeleiteten Objekt etwas anderes machen soll, auch im Konstruktor-Code schon.

    Wenn die Methode speziell dafür hergerichtet ist (im Allgemeinen jedenfalls), warum nicht. Das mit der Invariante ist auch eher ein theoretischer Einwand.



  • Bashar schrieb:

    Auch etwas, wo ich mich frage, was sie sich dabei gedacht haben. Ich sag nur Template Method ...

    Ich nix verstehen. 🙂





  • Du wirst sicher verstehen, dass ich mir dieses Buch jetzt nicht zulege, um deinen aus zwei Wörtern bestehenden Einwand zu verstehen. ;/

    Dann muss ich halt bei meiner Ansicht bleiben, dass es praktisch nicht nötig ist, private Methoden dynamisch zu binden, auch wenn insgeheim weiß, dass du wahrscheinlich mal wieder Recht hast. 😞

    EDIT: Das natürlich alles bezogen auf Java



  • Google: Template Method

    Der Witz bei diesem Pattern ist, dass eine private Methode von einer öffentlichen Methode aufgerufen wird. In einer abgeleiteten Klasse wird dann die private Methode überschrieben, um das Verhalten im Detail zu verändern. In Java müsste man diese Methoden dann anscheinend sichtbar machen, obwohl das völlig unnötig ist. Da ich nicht wirklich den Sinn darin sehe, dass private Methoden nicht dynamisch gebunden werden (dazu gibts doch final), frage ich mich eben, was Sun sich da gedacht hat.



  • Jo, da müsste man dann die "Detail-Methode" protected machen.

    Mir ist natürlich jetzt klar, dass die Kapselung mit einer virtual private Methode noch besser ist, weil die abgeleitete Klasse die Methode dann nur redefinieren aber nicht aufrufen kann.

    Prinipiell gefällt mir persönlich das System von beispielsweise C# auch besser, ganz einfach auch aus Performancegründen. Die JVM inlined glaub ich weniger winzigweich-Methoden (die fast nichts machen), als mir lieb sein kann, virtual kann auch einfach eine Hilfe für den optimierenden Compiler sein.



  • Hi

    @Optimizer

    weis ich seitdem auch. was man nicht mehr sieht mus nicht umbedingt wirklich tot sein, sondern kann auch noch im speicher weiter vegetieren und resorcen blockieren.

    @bashar

    Stell dir mal die situation vor, du verwendest ein Objekt von dem du nur die öffentlich Schnistelle kennst. ( wozu soll ich Interne private schnitstellen für andere documenteiren auser für mich? ich will ja schlieslich nicht alles verrathen oder) Dieses Leitest du ab um es zu erweitern. dummerweise erwischt du beim Namen deiner privaten Methoden einen der bereits im obj implementiert ist. dann wünsch ich viel spass beim fehlersuchen.

    ok sie müste unter c explizit virtuell deklariert werden. in Java ist das aber leider nicht der fall.

    auserdem kann das sein das du PrivatMethoden mit PrimitivMethoden verwechselst? Bei mir im Buch stand zumindestens beim überfliegen nichts davon drin primitivMethoden private zu implementieren.

    gruss Termite



  • Es wird schon der Punkt sein, dass man nicht aus Versehen private Methoden redefiniert, was in 99% der Fälle wahrscheinlich nicht gewünscht ist.
    Das ist eigentlich eine ziemlich gute Überlegung von dir, ich könnte mir vorstellen, dass das der Grund dafür ist, dass diese Methoden nicht dynamisch gebunden werden.

    Korrektur meiner obigen Aussage: Man müsste den Zugriffsschutz nicht auf protected setzen, sondern es würde package-private reichen. Was die sich mit dem protected gedacht haben, ist mir auch durch und durch ein Rätsel.
    Und C# muss ja auch gleich auftrumpfen mit protected, internal, internal protected. 🙄


Anmelden zum Antworten