Thema in Kurzform
Alle Klassen gehen auf eine oberste Superklasse zurück. Dieser "Urahne" heißt sinnigerweise Object.
Eine Object-Variable kann auf sämtliche Objekttypen verweisen.
In der Java-Bibliothek ist Object im Paket java.lang zu finden. Alle Klassen sind direkt oder indirekt von Object abgeleitet. Die Vererbung von Object wird in Java automatisch geregelt, sodass wir keine expliziten Code-Angaben (extends Object) dafür machen müssen:
public class Coconut extends Object {} // nicht nötig!
Eine Klasse wie hier mit extends Object zu definieren ist zwar möglich, aber überflüssig und sollte darum vermieden werden.
Für die Vererbungshierarchie in Bezug auf Object gilt:
Man kann also sagen, dass jede Klasse, die nicht explizit eine andere Klasse erweitert, implizit Object erweitert.
Alles klar soweit? Gut! Dann schauen wir uns jetzt mal an, was wir mit Object alles anstellen können.
Da alle Java-Klassen von Object abgeleitet sind, bekommen sie alle Methoden von Object vererbt. Diese Methoden sind überaus praktisch und können für jede Art von Objekt eingesetzt werden.
So lassen sich etwa mit der Methode equals() Objekte miteinander vergleichen. Oder sehen Sie sich die Methode toString() an, mit der wir einen "Namen" für Objekte zurückgeliefert bekommen.
Ein besonderer Teil der Object-Methoden sind für die nebenläufige Programmierung (Threads) bestimmt, wie notify() oder wait(). Das soll uns aber jetzt nicht weiter interessieren.
In folgender Übersicht sehen Sie eine Liste aller Methoden der Klasse Object:
Rückgabetyp | Methode und Beschreibung |
protected Object | clone() Erzeugt eine Kopie des aktuellen Objekts und liefert diese zurück. |
boolean | equals(Object obj) Prüft zwei Objekte auf Gleichheit. |
protected void | finalize() Wird vom Garbage Collector auf dem aktuellen Objekt aufgerufen, wenn das Objekt gelöscht wird. |
Class<?> | getClass() Liefert die Laufzeitklasse des aktuellen Objekts zurück. |
int | hashCode() Liefert den Hashcode-Wert des aktuellen Objekts zurück. |
void | notify() Weckt einen Thread auf, der auf das geschützte Objekt wartet. |
void | notifyAll() Weckt alle Threads auf, die auf das geschützte Objekt warten |
String | toString() Gibt eine String-Repräsentation des aktuellen Objekts zurück |
void | wait() Lässt den aktuellen Thread schlafen, bis ein anderer Thread notify() aufruft. |
void | wait(long timeout) Legt den aktuellen Thread solange schlafen, bis entweder ein anderer Thread notify() aufruft oder eine bestimmte Anzahl an Millisekunden (timeout) abgelaufen ist. |
void | wait(long timeout, int nanos) Legt den aktuellen Thread solange schlafen, bis entweder ein anderer Thread notify() aufruft oder eine bestimmte Anzahl an Millisekunden (timeout) abgelaufen ist, oder bis irgendein anderer Thread den aktuellen unterbricht, oder eine bestimmte Echtzeit abgelaufen ist. |
Kommen wir nun zum zweiten nützlichen Aspekt von Object. Da alle Klassen in Java von Object abgeleitet sind, bedeutet das, dass eine Variable vom Typ Object die ultimative polymorphe Variable darstellt. Das heißt:
Object ist also die Superbitch für alle Objekttypen. Sehen Sie selbst:
Object o1 = new Auto();
Object o2 = new Hund();
Object o3 = new Punkt();
Object o4 = new Coconut();
Egal welches Objekt von welcher Klasse: Eine Object-Variable vermag sie alle zu referenzieren.
Umgekehrt heißt das aber auch, dass jedes beliebige Objekt in den Typ Object gecasted (umgewandelt) werden kann:
Coconut coco = new Coconut();
Object o = (Object) coco;
Die alle Klassen umfassende Polymorphie von Object-Variablen können wir bei Arrays praktisch einsetzen. So wird es möglich, dass ein Array alle möglichen Objekttypen aufnehmen kann:
// Array für alle Objekttypen
Object[] array = {new Auto(),
new Hund(),
new Punkt(),
new Coconut()
};
Auch in Sachen Methoden-Parameter kann Object nützlich sein. So kann einem Object-Parameter jedes beliebige Objekt als Argument übergeben werden:
public class Coconut {
public static void takeAnything(Object o){
System.out.println(o.getClass());
}
public static void main(String[] args){
takeAnything(new Auto()); // class paket1.Auto
takeAnything(new Hund()); // class paket1.Hund
}
}
Stopp! Einen Moment mal! 🧐 Warum verwenden wir dann nicht immer Referenzen vom Typ Object für all unsere Objekte?
Die Antwort lautet, dass dies sehr gefährlich werden kann:
Object o = new Katze();
o.miau(); // funktioniert nicht!
Wenn wir eine Referenzvariable vom Typ Object deklarieren und ihr eine Instanz zuweisen, geht Java zur Compilierzeit davon aus, dass die Instanz ebenfalls vom Typ Object ist.
Doch tatsächlich ist der Objekttyp in unserem Beispiel nicht Object, sondern Katze! Die Konsequenz ist knallhart: Auf einem Objekt können nur diejenigen Methoden aufgerufen werden, die in der Klasse des Referenztyps (hier: Object) definiert sind. Da es die Methode miau() in der Klasse Object also nicht gibt, kann der Compiler die Anweisung o.miau(); nicht durchgehen lassen.
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]