140
Aufpassen!
Sebastian Eidecker edited this page 2019-11-19 06:56:15 +00:00

Kleinigkeiten, auf die ich aufpassen muss

  • Auf Sichtbarkeit/access modifier/falsche static-Zugriffe achten: Immer, an jeder Stelle, in jeder Aufgabe
  • Auf Importe achten
  • Auf fehlende Exceptions achten
  • Auf korrekte Definitionen von Methoden/Konstruktoren etc achten
  • Längen
    • Arrays: a.length
    • String: "Hallo".length();
    • StringBuilder: new StringBuilder("Hallo").length();
    • Listen: new ArrayList<>().size();
  • do-while-Schleifen
    • müssen mit einem Semikolon beendet werden
    • Klammern nicht erforderlich, wenn einzelne Anweisung (das kann auch eine andere Schleife sein, was sehr komisch aussieht)
    • do nicht erfoderlich, leere Anweisung while(i == 1); möglich. Dann ist es eine leere while-Schleife, das darüber liegende Statement gehört nicht zur Schleife, diese ist also leer!
  • Sichtbarkeit: Deklarationsbereich in for-Schleifen hat keinen eigenen Scope. Bereits deklarierte Variablen sind sichtbar, dürfen nicht unter selbem Namen neu deklariert werden.
  • Sichtbarkeit: Bereits deklarierte Variablen dürfen in einer Methode nicht neu deklariert werden, wenn sie sichtbar sind. Feldnamen können versteckt werden, auf sie kann dann per this. zugegriffen werden.
  • Initialisierung: Felder werden mit Standardwerten initialisiert (0, false, null, ...). Lokale Variablen nicht -> Compilefehler bei Zugriff! final deklarierte Felder müssen dennoch explizit initialsisert werden
  • Auf root-Ebene definierte Klassen und Enums dürfen nicht private sein (dann wären sie auch nie sichtbar). Als innere Klassen möglich.
  • Call by reference, call by value: Aufpassen auf Primitive
    • Strings und Wrapper sind Sonderfälle bei (Standard)-Objekten, da immer Immutable! Können nicht verändert werden, verhalten sich daher wie value-Calls
  • String-==: Strings, die per Konstruktor erzeugt wurden, lassen sich inhaltlich nicht per == prüfen, da echte Referenzen auf Heap. Strings, die per "" erzeugt wurden, haben gleiche Referenz, wenn inhaltlich gleich und können per == verglichen werden. Das gilt auch, wenn die Strings in anderen Methoden erzeugt und zugewiesen werden.
  • Definition Zahlen: int ist bei Ganzzahlen Standard, wenn kein Suffix. double ist bei GLeitkommazahlen Standard, wenn kein Suffix.
  • + - Operator: Ist erlaubt, wenn ein Argument ein String ist. Dann wird toString() auf dem anderen aufgerufen (Primitive gehen auch).
    • Geht: System.out.println(new StringBuilder("Hallo ") + "Welt");
    • Geht: System.out.println(new StringBuilder("Hallo ") + "Welt" + true);
    • Geht: System.out.println(true + "Welt");
    • Geht: System.out.println(new StringBuilder("Hallo ") + new StringBuilder("Welt").toString());
    • Geht nicht: System.out.println(1 + true);
    • Geht nicht: System.out.println(new StringBuilder("Hallo ") + new StringBuilder("Welt") + "Welt"); (Auswertung von links nach rechts)
  • Zuweisung Primitive außerhalb Wertebereich:
    • Compilefehler: char c = 1L; Explizit long ist zu groß
    • char c = (char) 1L; geht
    • Compilefehler: short sh = Short.MAX_VALUE; char s = sh;
  • Short-Circuit geht vor: Bei short-circuit werden Seiteneffekte nicht nach Operator-Vorrang, sondern nach short circuit-Regeln von links nach rechts angewandt.
  • Referenz abstrakte Klasse kann null zugewiesen werden: abstract class A {} -> A a = null; ist erlaubt.
  • Final-Klassen im JDK: Primitiven-Wrapper, System, String, StringBuilder, LocalDate sind final. Number nicht.
  • Polymorphie nicht bei Feldern: Felder werden auf dem deklarierten, nicht dem tatsächlichen Typ aufgerufen. Anders als bei Methoden. Dabei auch auf Compilefehler achten. Felder werden aber vererbt, sind also auch sichtbar (wenn Sichtbarkeit passend)
  • Exceptions:
    • RuntimeException ist eine Exception, wird also auch von catch (Exception e) gefangen
    • RuntimeExceptions müssen nicht gefangen oder deklariert werden.
    • Alle anderen Exceptions müssen deklariert und gefangen (oder wiederum deklariert) werden.
    • Todo: Müssen deklarierte Checked Exceptions geworfen werden? -> Nein
    • Dürfen nicht deklarierte CheckedExceptions gefangen werden? -> Nein (Exception, RuntimeExcpetion, Throwable, Error schon). Compilezeit-Typ zählt.
    • IOException ist eine checked Exception
    • Überschriebene Methoden dürfen keine neuen CheckedExceptions deklarieren, von vorhandenen dürfen Subklassen deklariert werden. (Dann bei super-Aufrufen die ursprüngliche Exception aber auch behandeln). Nicht deklarierte Exceptions der Oberklasse sind auch nicht vorhanden, müssen nicht behandelt werden (deklarierter Typ zählt).
Object
|
|
Trowable (Checked)
|
|------ Error (inkl. Unterbaum nicht Checked)
|       |
|       |------- ...
|
|------ Exception (Ab hier Checked außer Runtime)
        |
        |------- Runtime (inkl. Unterbaum nicht Checked)
        |        |
        |        |------ NumberFormatException
        |------
  • Konstruktoren und Vererbung:
    • super (auch this) erster Aufruf, auch nicht in try-Block einbettbar. Damit auch nur ein super oder this-Aufruf möglich.
    • Dadurch können Exceptions der Konstruktoren der Superklassen nicht gefangen und selbst deklariert werden
    • Konstruktor der Unterklasse kann dieselbe Exception oder eine Superklasse deklarieren (anders als beim Überschreiben, wo es Subklassen sind.
    • Konstruktoren werden nicht vererbt, damit nicht überschrieben!
  • ; (Leere Anweisung): Generell erlaubt, auch am Ende von Klassen. Nicht, wenn unreachable Code oder bei spezieller Syntax do {} while(i == ;) (Compilefehler)
  • do {} while(i == 1); - Semikolon am Ende!
  • Überschreiben: Rückgabe muss exakten Typ haben (bei Primitiven) oder alternativ Subklasse sein (bei Klassen)
  • 0 % 3 == 0
  • Ueberladen: null (als Schluesselwort kann nicht uebergeben werden, wenn der Compiler dadurch die Methode nicht eindeutig bestimmen kann. Wenn Typ bekannt ist, kein Problem.
  • throw null führt zu NullPointerException
  • switch: -ausdruck muss Typ enum, byte, short, int, char oder String ergeben
    • Vom Compiler berechenbare Audrücke in case-Anweisungen sind erlaubt (compile time constant). final int i = 1; geht, final int i; i = 1 geht nicht.
  • Erlaubte Identifier-Namen:
    • Müssen mit _, $ (Währungssymbol) oder Buchstabe beginnen
    • Danach auch Zahlen erlaubt
    • Kein reserviertes Schlüsselwort
    • Beliebig lang
    • Groß-/Kleinschreibung relevant
  • getClass() bezieht sich auf den Laufzeittypen
  • byte = byte + byte funktioniert nicht, da + in int konvertiert. cast erforderlich, sonst compilerehler
  • Wertebereiche:
Typ Bytes Bereich
byte 1 -2⁷ - 2⁷-1
char 2 0 - 65535
short 2 -2¹⁵ - 2¹⁵-1
int 4 -2³¹ - 2³¹-1
long 8 -2⁶³ - 2⁶³-1
float 4
double 8
  • char kann nur ein char zugewiesen werden, expliziter Cast erforderlich

  • Interface-Methoden sind immer implizit public, nicht jedoch abstract, wenn sie static oder default sind.

  • String/StringBuffer und Indizees

    • String (Immutable)
      • charAt() 0-based. Liefert char
      • length(): tatsaechliche Laenge
      • substring(int start): start zero-based (inklusive)
      • substring(int start, int end): end one-based! (inklusive)
      • Exception, wenn Index ausserhalb Bereich oder end < start. "" bei end == start
      • += definiert, weist dem String den neuen Wert auch zu. -= geht nicht. (Kann nur auf Variablen angewendet werden, nicht auf Literale!)
      • "Hallo".concat("Welt");
    • StringBuilder (Nicht immutable)
      • 0-based, 1-based => Inklusiv - exklusiv oder [start; end[ bei 0-based, jeweils vor dem Element
      • length(): tatsaechliche Laenge
      • indexOf: Erstes Vorkommen des Strings (erste Position). Zero-based
      • lastIndexOf
      • append(value, diverse Typen): Fuegt am Ende an
      • delete(start, end): start zero-based, end one-based. end darf ausserhalb index sein, start nicht (aber end nicht kleiner start). Bei start == end keine Änderung
      • insert(start, value in diversen typen: start zero-based (vor dem Zeichen)
      • substring(start, end): start zero-based, end one-based/ Liefert String als Rueckgabe, aendert Objekt nicht!
      • null als Literal kann nicht angehaengt oder eingefuegt werden, da dann ueberladene Methode nicht aufgerufen werden kann. (Wenn Typ klar, kein Problem, null als WErt zu übergeben)
      • Immer darauf achten, toString() aufzurufen
      • Nicht synchronized
      • Gibt kein firstIndexOf
      • Gibt kein concat
  • final-Felder: Müssen im Konstruktor oder Initialisierungsblock gesetzt werden. Standardwerte gelten hier nicht.

  • Fehlende Konsturktoren in Oberklasse: Ist kein parameterloser Konstruktor in Oberklasse vorhanden, muss ein anderer explizit aufgerufen werden. Andernfalls Compile-Fehler

  • Initialisierungsblöcke:

    • Werden der Reihenfolge nach abgearbeitet
    • Können nicht synchronized sein
    • Bilden jeweils einen eigenen Block (Sichtbarkeit)
    • Können auf danach deklarierte Felder und Methoden zugreifen.
    • Dürfen keine unbedingte Exception werfen. CheckedExceptions müssen vom Konstruktor deklariert werden.
  • if/else ohne Klammerung: Else gehört immer zum if davor.

  • instanceof:

    • Prüft Typgleichheit für Referenzen (nicht Klassen, nicht Primitive)
    • Laufzeit-Typ entscheidend
    • Kann nur auf Objekte derselben Klassenhierarchie angewendet werden (Sonst Compilerfehler)
    • True, wenn Objekt vom Typ der Klasse/Interface oder einer Subklasse davon (Is-a test)
    • null instanceof BeliebigerTyp ist immer false
    • instanceof null nicht möglich, ``null` ist kein Typ
    • Arrays (auch von Primitiven) sind Object
    • Variablen müssen für instanceof-Prüfungen initialisiert sein (oder Klassenvariablen, die einen Standardwert haben)!
  • Cast:

    • Bei primitiven und Objekten möglich
    • Bindet stark, oft Klammern erforderlich
    • Primitive
      • Expliziter Cast erforderlich, wenn Genauigkeit nicht ausreicht
      • Bei Zahlen kann so auch Genauigkeit verlorengehen
      • Bei +=, ... impliziter Cast, nicht explizit erforderlich
      • Bei Wrapper-Objekten darf nur exakter primitiver oder Wrapper-Typ-Cast erfolgen
    • Objekte
      • Cast außerhalb Typhierarchie erzeugt Compilefehler
      • Angegebener Typ im Cast muss Laufzeittyp des gecasteten Objekts oder Superklasse entsprechen
      • Angegebener Typ muss Typ der Variablen, der zugewiesen wird oder Subtyp entsprechen
      • null kann auf alles gecastet werden
      • In Typhierarchie ggf. ClassCastException, wenn doch nicht kompatibel
      • Sinnlose Casts sind erlaubt
      • Downcasting: Wenn Typ Oberklasse deklariert, aber Laufzeit Unterklasse: Zuweisung an Unterklasse per explizitem Cast möglich (ggf. ClassCastException zur Laufzeit)
      • Upcasting: Referenzen einer Unterklasse können ohne explizitem Cast einer Oberklasse zugewiesen werden.
  • Scope: Variablen im Scope dürfen nicht neu definiert werden. Auch z.B. nicht in for-Schleifenvariable.

  • LocalDate, LocalTime, LocalDateTime:

    • Sind immutable!
    • Sind unabhängig, nicht in einer Hierarchie. instanceof, equals, before == scheitern, meist Compilefehler
  • foreach:

    • Verwendbar mit Arrays und Klassen, die Iterable implementierten (also insbesondere Collection mit List, nicht aber Map)
    • Primitive können als Laufvariable verwendet werden.
    • Klammern im Body können weggelassen werden, dann nur eine Anweisung
  • Arrays:

    • Array-Index kann auch mit char, short, byte angesprochen werden, nicht aber mit long
    • Deklaration: [] können vor oder nach Variablennamen stehen, bei mehrdimensionalen auch gemischt davor und danach.
    • Bei Initialisierung muss [] nach dem Typen stehen
    • Niemals Deklaration und Größe in einem Schritt;
    • int[] ints = new int[] {1, 2, 3} geht (Länge darf nicht angegeben werden), int[] ints = {1, 2, 3} auch. int[] ints = new [5] int NICHT
    • Haben ein Attribut length zur Bestimmung der Größe
    • Multidimensionale Arrays sind Arrays von Arrays. Verschiedene Dimensionen können verschiedene Längen haben.
      • Bei Initialisierung müssen nicht alle Dimensionen angegeben werden, aber von links nach rechts, links dürfen keine fehlen.
      • Wenn nicht initialisiert => NullPointer (da Objekte)
      • int ints [][][][] = new int[3][3][][];. ints[1][2] = new int[][] {{1}{2}}, also mehrdimensionales Array. (Ander Stelle auch keine anomyme Array-Erzeugung erlaubt, new int[][] ist Pflicht
      • Bei ananomyer Erzeugung kann auch Variable mit Array verwendet werden: int [] one = {1,2,4}; int [][] tow = {one};
    • Bei Zuweisungen
      • Dimensionen beachten! Längen darin können geändert werden bei Zuweisung.
      • Unterschiedliche Dimensionen können unterschiedliche Länge haben, auch bei Zuweisung: int [][] a = {{1,2}, {1}}
      • Arrays von Primitiven: Wie Variablenzuweisung, sowohl geamtes Array als auch einzelner Wert. Kein impliziter oder expliziter Cast des Grundtyps möglich!
      • Arrays von Referenztypen: Is-A-Test, also Superklassen (Sowohl gesamte Arrays als auch einzelne Felder)
      • Cast per (Typ[]), instanceof int[]
      • Arrays erben auch von Object
  • ArrayList:

    • add: Am Ende hinzufügen
    • remove(Object): Entfernt das erste Element der Liste, Vergleich per equals
    • remove(int index): Zero-based Entfernen des Elements an Position
  • Zahl-Literale und Unterstriche:

    • Nicht am Anfang oder Ende erlaubt. (Bei double, float auch nicht vor oder hinter Dezimalpunkt)
  • Encapsulation: Beim Setzen und Rückgabe von Listen (und eigentlich allen komplexen Typen) Kopie erzeugen. Immutable Objekte Sonderfall.

  • Lokale Variablen und final-Felder: Bedingte Initialisierung: Wann meckert der Compiler?

    • Nur wenn der Compiler sicher ist, dass eine Variable initialisiert wurde, gibt es keinen Compilerfehler
    • Compiler prüft aber keine Bedingungen (if (true) genügt, if (b = true) nicht)
    • Bei Zuweisungen zu final ähnlich: Compiler ahndet Mehrfachzuweisung, wenn er Bedingung nicht eindeutig auflösen kann. if (true) s3= "Hallo"; if (false) s3 = "Welt"; geht, if (b) s3= "Hallo"; if (!b) s3 = "Welt"; geht nicht. final boolean c = false; if (c) s6 = "Hallo"; if (!c) s6 = "Welt"; geht, da c final ist.
    • Ähnlich bei try-catch: Wenn der Compiler sicher ist, dann erlaubt (Compile-Zeit-Konstanten, auf jeden Fall geworfene Exeptions, finally-Blöcke etc.)
  • Erlaubte und implizite Modifier

    • Interfaces: implizit abstract. Formal nicht public, können aber von überall verwendet werden. Wenn public, eigene Datei. Dürfen nicht protected oder private sein.

      • Methoden
        • default: implizit public, dürfen nicht private, protected, final, abstract, static sein.
        • static: implizit public, dürfen nicht private, protected, final, abstract, default sein.
        • Standard: implizit public abstract, dürfen nicht private, protected, final, static sein
      • Felder: Sind immer Konstanten, also implizit public static final
    • Klassen: Sichtbarkeit nur public oder <default> - bei public eigene Datei, final, abstract (nicht beides), strictfp

      • Methoden
        • Sichtbarkeit: public, protected, <default>, private
        • final, abstract: Nicht zusammen, abstract nur, wenn Klasse abstract, private abstract verboten
        • synchronized, native, strictfp
      • Felder
        • Sichtbarkeit: public, protected, <default>, private
        • final
    • Lokale (automatische) Variablen

      • Dürfen keine Sichtbarkeits-Modifier private, protectes, public haben
      • Können final sein
  • Implementierung 2 Interfaces

    • Interessant, wenn beide Interfaces dieselbe Methode deklarieren
    • Eine static, andere abstract => Abstrakte implementieren, die statische wird nicht vererbt!
    • Beide static => Zugriff direkt über Interfacename.methode(), nicht über super oder this. Wird ja nicht vererbt. Ist nicht Teil der Klasse, kann von außen auch nicht in der Klasse angesprochen werden, nur über das Interface. Kann aber in der Methode mit selbem Namen deklariert werden.
    • Beide abstract => Muss implementiert werden. Zugriff nur über this.
    • Beide default => Muss implementiert werden, um Eindeutigkeit zu schaffen! Zugriff per Interfacename.super.methode() möglich! Über this und von außen über Klassenreferenz sichtbar.
    • Oberklasse und default-Implementierung in Interface: Muss nicht implementiert werden, die Implementierung der Klasse gewinnt
    • Eine default (simpler Fall): Kann überschrieben werden. Zugriff auch per Interfacename.super.methode() möglich, super alleine genügt nicht! Über this und von außen über Klassenreferenz sichtbar.
  • Rangfolge der Operatoren, von stark zu schwach bindend.

Typ Symbole Beispiele Anmerkungen
Klammern, Array-Zugriff, Feld/Methodenaufruf (), [], . a[1], "Hallo".length()
Unäre Operatoren -, !, ++, -- -7 * 4, !myBoolean Post-Inkrement und -Dekrement erst in nächster Operation sichtbar
Cast und new (), new (int) 4L, new String("") Rechts nach links
Multiplikation, Division, Modulus *, /, % 7 % 4 / 0 erzeugt Exception
Addition, Subtraktion +, - 7 + 4
Relationale Operatoren <, >, <=, >=, instanceof y > x
Gleichheits-Operatoren ==, != y != x Referenz bei Objekten, nicht mi equals verwechseln! Sonderfall String!
Logische Operatoren &, | myBool & yourBool Beide Ausdrücke immer ausgewertet
Short-Circuit-Operatoren &&, || myBool
Ternärer Operator ? : x == true ? "Hallo" : "Welt" Reihenfolge rechts nach links!
Zuweisungs-Operatoren =, +=, -= x += 5 Zuweisung sehr niedrig priorisiert, und rechts nach links! (a = b = 3)
  • Bei gleicher Priorität von links nach rechts, durch Klammerung kann Vorrang geändert werden.

  • Vergleich und Gleichheit vor logischen Operatoren!

  • Assignment, Logisch, Gleich, Vergleich, Rechnen, Unary

  • Vararg:

    • methode(Typ ... name): ... mit oder ohne leerzeichen zwischen Typ und Variablenname
    • Nur ein Vararg, immer letzter Parameter
    • In der Methode ein Array
    • Beim Überladen wie Array
    • Vararg-Parameter kann mit Array aufgerufen werden, der vararg-Parameter kann in Array-Parameter übergeben werden
    • Nicht möglich: methode(1, 2, 3) als Aufruf für Array!
    • public static void main(String... args) ist gültige Signatur für Programmeinstieg
  • Lambda-Ausdrücke (hier Predicate)

    • Ermöglichen, Code als Parameter zu übergeben oder in einer Variable zu definieren. Dieser kann dann in anderen Methoden (in einem neuen Kontext) ausgeführt werden.
    • Predicate ist ein Interface und hat eine abstrakte Methode boolean test(T var1), die durch den Lambda-Ausdruck (oder eine Klasse, die Predicate implementiert) implementiert wird.
    • Lambda-Definition für Predicate: argument -> anweisung; private Predicate<Tour> tourstartFaehig = x -> x.isAbgeschlossen();
      • Ein Argument, kann, muss aber nicht umklammert werden. Kann Typ deklarieren, muss dann geklammert werden (String s) -> s.length() == 1;
      • Mehrere Anweisungen in {}, dann return notwendig. (Bei Predicate boolean). Auf korrekten Block achten, ; auch hinter letzter Anweisung.
  • Postinkrement:

    • Wird erst nach der Anweisung ausgeführt: callMethod(i++);. Es wird der alte Wert übergeben!
    • callMethod(i++ + i);: Sei i = 1: Das zweite i ist schon erhöht, also 2. Nach der Anweisung ist i = 2;
    • += wird vor Übergabe ausgeführt
  • Interface-Default-Methoden: Die implementierende Klasse darf keine private gleiche definieren

  • Generell Überschreiben: Methode in Unterklasse darf Sichtbarkeit nicht einschränken, auch nicht auf private

  • Überladen und Überschreiben: Bei Fragen, was eingefügt werden dard: Überladen parallel zu Überschreiben möglich!

  • Abstrakte Klassen können Konstruktoren besitzen: Wie bei gewöhnlichen Klassen, sie können aber nicht instanziiert werden. (Interfaces haben keine Konstruktoren)

  • Exceptions in Konstruktoren: Klassen müssen konstruiert werden können. Wenn implizit ein Konstruktor der Oberklasse aufgerufen wird, muss der Konstruktor dieselben Exceptions oder Superklassen davon deklarieren. Da super() immer die erste Anweisung ist, kein try/catch möglich. Aber kein 1:1-Bezug, da per this andere Konstruktoren aufgerufen werden können. Compilefehler im Konstruktor (super-Aufruf), der fehlerhaft ist.

  • Wrapper

    • Keine Ganzzahl-Literale für Float und Double. Konstruktoren schlucken aber Ganzzahlen!
    • Postinkrement-Operatoren möglich (erzeugt aber neue Referenz!)
    • equals beachtet Typ, nicht nur Zahlwert
    • == ist klassische Objektreferenz
      • Es gibt aber Ausnahmen, bei denen sich Wrapper wie String verhalten (Definition per Literal, nicht per new) und primitiver Wert verglichen wird: Boolean, Byte, Character von \u0000 bis \u007f, Short und Integer von -128 bis 127 (== geht aber weiterhin nur auf demselben Typ! Sonst Compilefehler)
      • Short short1 = 127; Short short2 = 127; Short short3 = 128; Short short4 = 128; assertTrue(short1 == short2); assertFalse(short3 == short4);
    • Immutable (Primitive selbst sind mutable!)
    • == zwischen Wrapper und Primitivem: Wrapper wird ausgepackt, beide Primitive verglichen!
  • Methodensichtbarkeit: private final erlaubt (aber sinnlos)

  • static-Sichtbarkeit:

    • Statische Methoden nicht vererbt, aber in Subklasse sichtbar
    • Es darf keine sonst gleiche, nichtstatische definiert werden (Regeln wie Überladen, Typ in Hierarchie genügt, Rückgabe nicht)
    • Auch innerhalb einer Klasse darf keine statische und nichtstatische Methode mit gleicher Signatur definiert werden.
    • Eine identische statische Methode darf definiert werden (ist aber nicht überschrieben, da statisch). Auswahl daher per Compilezeit-Typ, nicht polymorph)
    • Feld mit demselben Namen darf in Ober/Unterklasse definiert werden. Dann kommt es beim Zugriff auf den deklarierten Typen an!
    • In einer Klasse darf Name nicht doppelt vergeben werden, wie bei Methoden.
  • Polymorphie und Überladen

    • Signatur zur Compilezeit, also der definierte Typ. Es wird aber die Methode des tatsächlichen Objekts ausgeführt, sollte diese zusätzlich überladen sein. Wenn Methode nicht in der deklarierten Klasse vorhanden ist -> Compilerfehler.
  • Überschreiben vs. Überladen:

    • Überladen: Argumentliste muss sich ändern (exakter Typ zählt), damit Methode unterschiedlich ist. Rest egal, zählt aber nicht zur Unterscheidung.
    • Überschreiben: Argumentliste darf sich nicht ändern (exakter Typ zählt). Exceptions können wegfallen, keine neuen oder Superklassen der vorhandenen. Sichtbarkeit nicht restriktiver, großzügiger geht. Rückgabe höchstens Subklasse.
  • Import nicht sichtbarer Objekte ist verboten -> Compilefehler

  • import org.eidecker.oca8lernen.lastminute.Oberklasse.* importiert nicht Oberklasse. Ist aber erlaubt für innere Klassen!

  • Neudefinition nicht sichtbarer Methoden

    • private-Methoden dürfen in der Unterklasse neu definiert werden
    • Auch nicht sichtbare package-private Methoden können neu definiert werden. (Höllisch aufpassen bei Polymorphie, ist nicht überschrieben): Je nachdem, in welchem Pakage der Aufrufer ist sieht er unterschiedliche Methoden, Cast kann Methode sichtbar/unsichtbar machen.
  • Interfaces können mehrere Interfaces erweitern

  • Cast in Klassenhierarchien

    • Compiler jammert, wenn Cast außerhalb Hierarchie (Deklarierte Compilezeittypen zählen)
    • Runtime-Exception, wenn Laufzeittypen dann tatsächlich nicht passen (Unterklassen können immer Oberklassen zugewiesen werden, auch ohne Cast)
    • Todo: Nur lineare Hierarchie zählt? Ja, bei Betrachtung der deklarierten Compilezeittypen
      • Direkte Zuweisung, wenn passender oder Subtyp
      • Cast, wenn theoretisch irgendwie ein passendes Objekt zugewiesen werden kann.
      • Der Cast-Typ selbst muss passender Typ oder Subklasse sein
    • Bei Zweifeln Hierarchie deklarierter Typen aufmalen! Die zählen!
  • equals(): Wenn nicht überschrieben Ergebnis wie ==

  • Konzept-Fragen:

    • Schon die Tatsache, dass alles von Object erbt und Methoden wie System.out.println toString auf beliebigen Objekten aufrufen können, genügt als Argument für Nutzung von Polymorphismus.
    • Genauso gilt Aufruf von toString als Nutzung von Vererbung.
    • .class-Files provide good security - Also Werbeaussagen zu Security bejahen
  • For-Schleife: Die Anweisung wird am Ende der Schleife erhöht! Im Body ist also der Wert bei Prüfung sichtbar!