Java Ausgaben schreiben

sasbro97

Lt. Junior Grade
Registriert
Nov. 2014
Beiträge
417
Hey Leute, in meiner Programmierung Klausur wird es erneut vorkommen, dass ich einen Quellcode bekomme und dann Aufrufe in der Main-Methode gegeben sind und ich quasi Compiler spielen muss und sagen muss, wenn etwas falsch ist oder was die genaue Ausgabe ist. Ich verstehe die Aufrufe aber teilweise überhaupt nicht.

Hier bspw. bei d) und f) kann mir das jemand erläutern? Was wird denn bitte bei d) aufgerufen, dass die Ausgabe: Z: v1=70 v2=8 v3=40 lautet.
Dachte der Debugger hilft mir, aber wohl kaum bei print...

Java:
public class TestJava {



    public interface I { public void a(int v1); }



    public static abstract class X implements I {

        protected int v1=70;

        public int v2=20;



        public void a(int v1) { v2 = v1; }

   

        public void print() { System.out.println("X: v1=" + v1 + " v2=" + v2); }

    }



    public static class Y extends X {

        int v3 = 33;

   

        public void b(int v2) { v3 = this.v2; v1 = v2; }

   

        public void print() { System.out.println("Y: v1=" + v1 + " v2=" + v2 + " v3=" + v3); }

    }



    public static class Z extends Y {

        static int v2 = 8;

        private int v3 = 40;

   

        public void a(int v1) { super.a(v1); this.v1 = v1;}

        public void b(int v2) { v2 = this.v2;}

   

        public void print() { System.out.println("Z: v1=" + v1 + " v2=" + v2 + " v3=" + v3); }

    }



    public static void main(String[] args) {

        //ERGAENZUNGEN HIER

        X x; Y y; Z z; I i;

   

        System.out.println("a)");

        y = new Y();
        z = new Z();
        y.print();
        z.print();    

   

        System.out.println("b)");

        y = new Y();
        y.b(42);
        y.print();

   

        System.out.println("c)");

//        x = new X();
//        x.a(27);
//        x.print();

   

        System.out.println("d)");

        y = new Z();
        y.b(111);
        y.print();

   

        System.out.println("e)");

//        i1 = new Y();
//        i1.a(7);
//        i1.print();

   

        System.out.println("f)");
        x = new Z();
        x.a(55);
        x.print();
    }
}
 
Zuletzt bearbeitet:
Setzt du BITTE mal deinen Quellcode in die Code Tags vom Forum? Das ist grauenhaft zu lesen
 
1528806166214.png
 
Java:
public class SoSchautsAus {
   
    public static void main(String[] args) {
       
        system.out.println("Sowas hier!");
    }
}
 
So nun hab ich es. Kannte die Funktion nicht. Danke dir @Grimba
 
Fast, drück mal auf Bearbeiten und schreibe mal direkt hinter das erste CODE

=java

mit in die Klammer, also CODE=java

und bitte geh mal etwas sparsamer mit Leerzeilen im Quellcode um.
 
Hab kurz gebraucht. Bevor hier direkt die Lösung gepostet wird, denk bitte darüber nach was super.a(v1) genau aufruft und welche v1/v2 gesetzt werden (aka beachte this.v1 / this.v2 und was das bedeutet)
 
Im gleichen Zuge zu dem was ProGramer sagt, beachte, in welcher Hierarchie die Klassen bzw. Interfaces (und damit spoiler ich sogar etwas...) zueinander stehen und welche Art von Klassen das genau sind. Das hilft dir zu beurteilen, ob so manches new überhaupt geht.....
 
Ich erkläre mal wie ich es verstehe. y ist eine neue Instanz von Z. Was ich schon nicht so ganz verstehe, weil ich denke y gehört doch zur Klasse Y. Dann wird void b(int v2) in Klasse Z aufgerufen. Bedeutet die übergebenden 111 sind hier wegen this.v2 = 8. Und wenn ich dann y.print() mache sollte ich doch wenn nur als Ausgabe v2=8 v3=40 haben, aber wo kommt v1 her?
Ergänzung ()

@Grimba mir ist bewusst das c) nicht geht, weil X abstract ist und man davon keine Instanz erstellen kann. Genauso bei e) geht es auch nicht, aber das verstehe ich nicht ganz. Ich weiß der Fehler ist: I hat keine Methode print(). Abeeeer wieso I? Ich denke wir machen hier mit i1 = new Y(); eine neue Instanz der Klasse Y und kein Interface.
 
Was c) angeht, da liegst du richtig.

Was e) angeht, schau mal genau hin. Von welchem Typ ist denn i1? War jemals vorher schon von i1 die Rede?
 
@Grimba Hmm nein. Was wäre, wenn es i wäre anstatt i1? Dann wäre ja trotzdem das print() Problem. Aber ich dachte i ist dann eine neue Instanz von Y. Aber es greift wohl trotzdem irgendwie auf das Interface zu. Also greift bei y = new Z(); also auch auf Klasse Y zu oder versteh ich das falsch?
 
Erstmal, da i1 keinen Typ besitzt, und damit irgendwie aus der Luft gegriffen ist, könnte an dieser stelle auch einfach bratwurst stehen, Java wüsste nichts damit anzufangen.

Dann schau mal hier:

https://stackoverflow.com/questions/7275844/interface-as-a-type-in-java

if a variable is declared to be the type of an interface, its value can reference any object that is instantiated from any class that implements the interface.

Du könntest also durchaus einer Variable i vom Typ des Interfaces I ein Objekt zuweisen, welches I implementiert. X tut das. Und Y erbt von X. Damit ist jedes Y auch implizit ein X. Daher implementiert folglich auch Y I und damit wäre das gültig.

Instanziieren von I geht natürlich nicht.

Dein Problem ist hier aber schlicht die 1 zuviel.

edit: Um etwas mehr auf deine Frage einzugehen: Z erbt von Y, Y erbt von X und X implementiert I. Damit wäre
Java:
I i = new Z();
gültig.

Achja, und es gäbe dann natürlich eine print() Methode, weil es die spätestens seit X gibt.
 
Zuletzt bearbeitet:
Dann sag ich dir was der Compiler und mein Professor bzw. der Lehrstuhl sagt:
I i = new Y();
i.a(7);
i.print(); \lsg{Fehler: I hat keine Methode print()}

Somit gibt es keine print Methode. Extends hin oder her. Dass man auf andere Klasse wenn man extends und implements hat zugreifen kann ist mir bewusst.
 
Das Objekt hat eine Print Methode, wenn du das zu X castest, funktioniert das einwandfrei.
Der Fehler kommt daher, dass die Variable als I deklariert ist, der Compiler also nur sicher weiß, dass das Objekt die Methoden hat, die das Interface I voraussetzt.
 
Aaah, okay. Wieder was gelernt. Dann ist wohl nur der implementierte Teil des Interfaces selbst in der jeweiligen Klasse sichtbar, weil ja nur aus Typ I Sicht. Interessant. Der Cast behebt das dann, Danke auch Ebrithil.
 
@Ebrithil tut mir leid das hab ich nicht ganz verstanden. Bei Aufgabe f) ist es ja auch so, dass:
x = new Z();
x.a(55);
x.print();
Der Print findet schlussendlich ja doch in der Klasse von Z statt, also wird dort aufgerufen. Wieso klappt das dann nicht genauso beim Interface?
Die Methoden werden ja in den Klassen der Variablen also klein x y z aufgerufen, aber die Print-Methode findet in der angegeben klasse bei new ... statt. Wieso haut das dann nicht hin, wenn i doch in Y print benutzen müsste. Oder muss das Interface dieselben Methoden haben, damit es klappt?
 
@sasbro97
Der Compiler weiß ja nicht von welchem Typ das Objekt in Wirklichkeit ist.
Der hat nur die Information, hier ist eine Variable vom Typ I und auf dieser Variable wird versucht die Methode print() aufzurufen. Also guckt der Compiler, ob der Typ I oder eine seine Superklassen eine print() Methode besitzt. Da dies nicht der Fall ist funktioniert der Aufruf nicht.
 
@Ebrithil Puuuuh. Find ich immernoch irgendwie schwer zu verstehen. Ich versuch mir das einfach so zu merken, dass die Print-Methode immer den new ... Operator aufruft und die ganz normalen Methoden noch variablengebunden sind und dass jede Klasse von der Variable (hier i) dieselben Methoden besitzen muss.
 
@sasbro97
Die print Methode hat mit dem new Operator überhaupt nichts zu tun, ich versuchs nochmal deutlich zu erklären.

Java:
X x = new X();

I i = x;

Der new Operator erstellt ein Objekt vom Typ X. Dieses Objekt X besitzt alle Methoden die die Klasse X oder eine seiner Superklassen implementiert.
Dieses Objekt wird einer Variable vom Typ X zugewiesen, dadurch weiß der Compiler, dass hier alle Methoden der Klasse X zur Verfügung stehen.

Wenn dieses Objekt nun einer Variable vom Typ I zugewiesen wird, was geht, da X das Interface I implementiert, weiß der Compiler bei der Verwendung der Variable i nur, dass das Objekt, auf das i zeigt alle Methoden besitzt, die das Interface I definiert. Hier gibt es keine print Methode, deshalb gibt's die Fehlermeldung.

Das Objekt selbst hat allerdings noch immer die print Methode. Wenn ich als Programmierer also sicher weiß, dass das Objekt auf das i zeigt also vom Typ X oder einer Subklasse von X ist, kann ich i zu X casten und den Compiler damit zwingen das Objekt als X und nicht als I zu behandeln und print aufrufen.

Das sähe dann so aus:
Java:
((X)i).print(); //läuft!
 
Zuletzt bearbeitet:
Zurück
Oben