ich bin gerade auf eine Schleife mit Switch-Anweisung gestoßen, die ich absolut nicht verstehe. Die Zwischenschritte der Schleife kann ich nicht einmal ansatzweise nachvollziehen. Die Schleife sieht wie folgt aus:
int a = 5 ;
int b = a - 2 ;
for ( int i = a ; i <= a + 3 ; i++) {
switch ( i % 4) {
case 0 : a = a - 1 ; b = b - 4 ;
case 1 : a = a + 1 ; b = b + 2 ;
case 2 : a = a - 1 ; b = 2 + b ;
}
}
Mit meiner Berechnung kam ich auf a= 4 und b= 3
Die Musterlösung sieht da aber ganz anders aus. Nicht mal die Berechnungen stimmen mit meinen überein:
Ich schätze mal, dass es an der fehlenden break anweisung liegt. Aber in wiefern macht das so einen bösen Unterschied aus? Und wie genau geht das Programm hier vor? Was wird hier genau berechnet?
Ich schätze mal, dass es an der fehlenden break anweisung liegt. Aber in wiefern macht das so einen bösen Unterschied aus? Und wie genau geht das Programm hier vor? Was wird hier genau berechnet?
Wenn die break-Anweisung (lustig übrigens: In der Musterlösung steht brake [also Bremse]) fehlt und er in einen Case reinspringt (z. B. case 0), wird der Code aller folgenden Case-Anweisungen auch ausgeführt! Das heißt, wenn er in case 1 reinspringt, wird auch noch case 2 ausgeführt usw.
Achso. Jetzt ergibt die gesamte Rechnung auf einmal einen Sinn. Vielen Dank Und wenn ich ja schon dabei bin, kann ich ja noch eine kurze Frage einwerfen. Und zwar können Abstrakte Klassen und Interfaces ja keine Objekte erzeugen. Man kann dort ja auch sinnvollerweise keine Konstruktoren definieren. Aber mein Prof meinte mal, dass jede Klasse den Default-Konstruktor hat. Gilt dies auch für Interfaces, finale Klassen und Abstrakte klassen, oder sind diese Klassen davon ausgenommen?
Sorry für den Spam, aber es wäre echt gut, wenn ihr mich kurz aufklären könntet
Interfaces können keine Implementierungen beinhalten. Daher auch keine Konstruktoren. Sie können auch keine Konstuktoren „erzwingen“.
Abstrakte Klassen können Implementierungen enthalten in FOlge dessen können diese auch KOnstruktoren beinhalten.
Man kann aber keine Instanz einer abstrakten Klassen erstellen, da diese ggf. Methoden hat, die nicht implementiert sind. Dies sind eben abstrakte Methoden.
Von finalen Klassen kann man keine weitere Ableitung erstellen, ansonsten unterliegen sie den anderen Einschränkungen.
Wow, vielen Dank, dass du dir diese Umstände machst …Also, damit ich das richtig verstehe: Eine abstrakte Klasse kann einen Konstruktor beinhalten. Ich kann mehrere Klassen aber nicht von einer abstrakten Klasse erben lassen, wie z.B. so:
public abstract class Abstr {
public abstract String getHelloWordldString(String name);
}
public class Ab1 extends Abstr {
....
}
public class Ab2 extends Abstr {
....
}
Stimmt das soweit, oder habe ich das falsch verstanden?
Doch kannst du, aber diese müssen dann natürlich String getHelloWordldString(String) implementieren, sofern diese selbst nicht als abstract deklariert wurden.
Aber man kann natürlich keine Instanzen erzeugen, d.h. Ab1 ab = new Ab1() oder besser Abstr ab = new Ab1() ist möglich, aber Abstr ab = new Abstr() nicht.
Zu den default Konstruktoren: Wenn du in einer Klasse keinen Konstruktor definierst, dann gibts quasi automatisch einen Konstrutor ohne Parameter und Code. Wenn du aber public Ab1(String) schreibst, kann man nicht mehr new Ab1() aufrufen. Da müsste man dann wieder so was machen:
private int size;
public Foo(int size) {
this.size = size;
}
public Foo() {
this(1); // rufe obigen Konstruktor auf
}
}```
Zu oben: Die “switch”-Variable kann nur den Wert 0 bis 3 annehmen, bei 3 passiert gar nix, auch werden die anderen cases nicht betreten, wenn dort keine break’s sind. Allerdings ist es empfehlenswert, diese zu schreiben. Innerhalb der Schleife erfolgt kein Schreibzugriff an die Schleifenzählvariable i, insofern wird die Schleife immer genau 4-mal (3 + 1) ausgeführt werden.
Ohne weitere Angabe ist bei allen instanziierbaren Klassen immer ein öffentlicher Konstruktor ohne Parameter(variablen) vorhanden.
Edit 2: Die Schleifeninvariante wäre dann, dass jedes Case genau einmal ausgeführt wird, sich dessen Reihenfolge aber ändern kann. Was dann mit a und b geschieht, das muss man dann zusammenrechnen (vermute ich mal).
Ich will es nicht beim BLog als Kommentar schreiben, aber soweit ich weiß, “sollte” man sich das public vor den Methoden in einem Interface sparen, weil es in einem Interface keine nicht-public Methoden gibt. Offenbar kann man es aber auch hinschreiben. Da ich das ohne Quellenangabe einfach nur so im Kopf habe, stelle ich das mal hier zur Debatte: Gibt es da eine klare Richtlinie, was “schöner” ist?
Ich lasse das public auch immer weg, weil es einfach überflüssige Schlüsselwörter spart.
Im Gegensatz zum Weglassen vom Aufruf des parameterlosen Konstruktors einer Elternklasse sind mir hierbei auch keine “Nebenwirkungen” bekannt.
Edit: das mit dem Konstruktor wirkt vllt. ein wenig OT, aber mein Gedanke dabei war, dass man den Konstruktoraufruf weglassen kann, aber eben auch durch den Aufruf etwas explizit verdeutlichen kann. Diese Möglichkeit hat man beim public Schlüsselwort nicht.