Vergleich C++/Java


... [ Seminar WWW und JAVA] ... [ Thema Überblick über die Sprache Java ] ... [ Klassenbibliotheken ] ...

Übersicht


Variablen

Alle Variablen und Elemente von Objekten werden in Java automatisch initialisiert. Variablen werden bei ihrer Definition initialisiert, Elemente von Objekten beim Aufruf des Konstruktors.

Anfangswerte für die einzelnen Typen:

Typ

Anfangswert

boolean

false

char

'\u000'

Ganzzahl (int, byte, short, long)

0

Gleitkomma

+0.0

andere Referenzen

null

1. Instanzvariablen:
Werden initialisiert, wenn ein Objekt erzeugt wird. Für eine komplexere Initialisierung als mit den einfachen Variablenstartwerten gibt es Konstruktor-Methoden, die ausgeführt werden, wenn eine neue Instanz der Klasse erzeugt wird.

2. Klassenvariablen:
Werden initialsiert, wenn die Klasse das erste Mal geladen wird. Man kann Initialisierungsmethoden für Klassenvariablen schreiben (sog. statische Initialisierer), die benötigt werden für Klassen, die native-Methoden implementieren.

3. lokale Variablen:
Sind nur im Rumpf der Schleife und während der Initialisierung gültig.

Beispiel für 1. und 2.:

Beispiel für 3.:

=> Compilerfehler, weil die lokale Variable nur bis vor dem Semikolon Gültigkeit hat


Unterschied Wert <--> Referenz

Als einfache Datentypen werden die vordefinierten Datentypen bezeichnet. Objekte und Arrays werden als nicht-einfache Datentypen bezeichnet bzw. als Referenzdatentypen.

In Java gilt:

  • einfache Typen werden immer durch den Wert übergeben
  • Arrays und Objekte werden immer durch Referenz übergeben
  • Die Änderung einer Referenz innerhalb einer Funktion hat keine Wirkung nach "außen":
    => clonen
    => "per Hand"

    Beispiel:
    Weil Objekte per Referenz übergeben werden, können 2 Variable dasselbe Objekt referenzieren:

    Dies gilt nicht für einfache Typen:

    Objekte kopieren

    => die Variable a enthält eine Referenz auf das Objekt, welches von b refereziert wird
    => das Objekt das a referenziert hat, ist verloren

    Um Daten von einem Objekt in ein anderes zu kopieren, benutzt man die Methode clone(). Die clone()-Methode erzeugt ein neues Objekt desselben Typs wie das Ursprungsobjekt und initialsiert die Datenfelder des neuen, klonierten Objektes mit den aktuellen Werten der Datenfelder des Ursprungsobjektes:

    => die Variable c enthält ein Duplikat des von b referenzierten Objektes

    Java hat keine Zeiger

    Gründe:


    Arrays

    Anlegen von Arrays

    1. Möglichkeit: mit new

    => die Elemente des Arrays werden auf den Standardwert ihres Typs initialisiert
    => int_Array-Elemente auf 0 initialisiert
    => die Arrays von Objekten auf null initialisiert

    2. Möglichkeit:
    dynamisches Anlegen eines Arrays und Initialisierung mit den angegebenen Werten

    Ein mehrdimensionales Array wird mit new angelegt, indem die entsprechende Anzahl von Elementen in [] für jede Dimension angegeben wird:

    Bei allen Arrayreferenzen wird der Index überprüft. Liegt der Index außerhalb der Grenzen, so wird eine ArrayIndexOutOfBoundsExecption erzeugt.

    Die Größe eines Arrays ist nicht Teil seines Typs, d.h. es kann eine Variable deklariert werden, die z. B. vom Typ String[] ist, und ihr ein Array aus String- Objekten zuweisen, egal wie lang dieses Array ist:

    Zusammenfassung:


    Operatoren

    wie in C++

    Folgende Operatoren werden in Java nicht unterstützt:

  • Kommaoperator
  • * und &-Operatoren
  • sizeof-Operator
  • Neu:

  • +-Operator:
    wird auf String-Werte angewendet; ist nur ein Operand ein String, so wird der andere in einen String konvertiert; diese Umwandlung geschieht bei einfachen Datentypen automatisch und bei nicht-einfachen Datentypen durch den Aufruf der Methode toString()
  • instanceof:
    prüft, ob der linke Ausdruck eine Instanz der durch den rechten Operator angegebenen Klasse ist. Das bedeutet, daß der linke Operand ein Referenztyp sein muß. Der rechte Operand ist ein Typ- (bzw. Klassen-) Bezeichner.
    instanceof liefert true, wenn das Objekt auf der linken Seite eine Instanz der Klasse ist, die auf der rechten Seite angegeben ist
    instanceof liefert false, wenn das Objekt auf der linken Seite den Wert null hat (null-Referenz ist keine Instanz irgendeines Objekttyps)
  • >>>:
    alle integralen Typen in Java sind vorzeichenbehaftet, dieser Operator behandelt den Wert, der geshiftet werden soll, als nicht vorzeichenbehafteten Wert und schiebt die Bits mit einer Nullerweiterung nach rechts
  • & und |:
    integrale Typen wie in C++
    boolean: beide Operanden werden ausgewertet, auch wenn das Ergebnis schon feststeht (nachdem der linke Operand ausgewertet ist)
  • [] (Zugriff auf Felder) und . (Zugriff auf Einträge) werden in Java nicht als Operatoren gewertet
  • keine Operatorüberladung möglich
  • Typkonvertierung

    numerische Konvertierungen

    Wenn eine Variable in einen anderen Typen konvertiert werden soll, so muß ihr einfach der gewünschte Typ in Klammern vorangestellt werden:

    Bei Konvertierungen muß berücksichtigt werden, daß mit der Konvertierung ein Verlust an Genauigkeit sowie eine Einschränkung des Wertebereiches einhergehen kann. Es gibt folgende Regeln:



    Anweisungen (if/else, while und do/while)

    wie in C++

    Unterschied:
    null und 0 sind in Java nicht gleich false, und Werte ungleich 0 und nicht-null Werte sind nicht das gleiche wie true

    Es gibt kein goto-Konstrukt.


    Garbage Collection

    In Java gibt es kein Gegenstück zum new-Operator, das ein Objekt wieder entfernt. Auch Destruktoren im Sinne von C++ gibt es nicht. An Stelle expliziter Freigabe von Objekten gibt es einen Mechanismus, der sich automatisch darum kümmert: der Garbage Collector.
    Der Garbage Collector prüft, ob es noch Verweise auf ein Objekt gibt. Wird ein Objekt von niemanden mehr referenziert, wird es automatisch freigegeben.
    Java gibt keine Garantien, wann die Garbage Collection stattfindet oder in welcher Reihenfolge die Objekte freigegeben werden.
    Garbage Collection gibt automatisch die Speicherressourcen von Objekten frei, aber Objekte können noch andere Ressourcen besitzen, wie Dateideskriptoren oder Sockets. Der Garbage Collector kann solche Ressourcen nicht freigeben, deshalb muß man finalizer-Methoden schreiben, die z. B. offene Dateien schließen, Netzwerkverbindungen beenden.
    Wenn ein Objekt einen Finalizer hat, so wird diese Methode aufgerufen, bevor der Garbage Collector das Objekt löscht. Nach dem Aufruf des Finalizers werden die Objekte nicht sofort freigegeben. Der Grund ist, daß der Finalizer ein Objekt "wiederbeleben" kann, indem es den this-Zeiger irgendwo speichert, so daß das Objekt wieder eine Referenz hat.

    Beispiel:


    import-Anweisung

    Die package-Anweisung dient dazu, eine Sammlung von Klassen zu einer Einheit zusammenzufassen. Um die Zugehörigkeit einer Quelldatei zu einem Package anzugeben, wird vor der Deklaration von Klassen eine Package-Anweisung in der Quelldatei eingefügt. Dem Schlüsselwort Package folgt der Package-Name.

    Zum Importieren eines Packages oder einer Klasse aus einem Package definiert Java die import-Anweisung. Diese Anweisung stellt Javaklassen für die aktuelle Klasse unter einem abgekürzten Namen zur Verfügung.
    import stellt weder die Klasse zur Verfügung , noch "liest" es sie tatsächlich ein, sondern es spart nur Schreibarbeit und macht den Kode lesbarer.
    Es ist eine beliebige Anzahl von import-Anweisungen möglich. Sie müssen aber nach der optionalen package Anweisung am Anfang der Datei stehen und vor der ersten Klassen oder Schnittstellendefinition in der Datei.

    Es sind 3 Formen möglich:

    1. Form: import package;
    ermöglicht dem angegebenen Paket durch den Namen seiner letzten Komponente angegeben zu werden

    2. Form: import package.class;
    ermöglicht es der angegebenen Klasse in dem angegebenen Paket nur durch den Klassennamen benutzt zu werden

    3. Form: import package.*;
    alle Klassen des Paketes werden durch ihre Klassennamen verfügbar gemacht

    Werden 2 Pakete, die Klassen mit gleichen Namen haben, importiert, kommt es zu einer Fehlermeldung, wenn eine Klasse mit ihrem nicht mehr eindeutigen kurzen Namen benutzt wird.


    Subklassen und Vererbung

    Durch Vererbung können Klassen definiert werden, die auf einer anderen Klasse basieren. Diese neuen Klassen stellen eine Erweiterung und Spezialisierung ihrer Basisklasse dar. Die Subklasse kann neue Methoden und Elemente hinzufügen oder bestehende Methoden überschreiben. Wenn von einer Klasse einen Subklasse abgeleitet wird, muß die Subklasse im Kopf ihrer Deklaration das Schlüsselwort extends benutzen. Hinter extends muß genau eine Klasse angegeben werden.

    Modifier für Klassen

  • abstract:
    abstrakte Klassen dienen nur dazu, eine Klassenstruktur festzulegen, ohne Implementierungen vorzunehmen. Eine abstrakte Klasse darf nicht instantiiert werden. Von ihr muß erst eine Unterklasse abgeleitet werden, die die Methoden der abstrakten Klasse implementiert.
  • final:
    von Klassen, die mit final gekennzeichnet sind, können keine Unterklassen abgeleitet werden.
    Eine Klasse darf nicht gleichzeitg als abstract und final deklariert werden.
  • Modifier für Methoden

  • final:
    Eine mit final gekennzeichnete Methode kann nicht überschrieben werden.
  • static:
    static-Methoden gelten implizit als final und können deshalb nicht überschrieben werden.
  • abstract:
    Abstrakte Methoden sind dazu gedacht, die Aufrufstruktur, aber nicht aber die Implementierung festzulegen. Sie müssen in einer Subklasse implementiert werden, die nicht abstrakt ist. Abstrakte Methoden dürfen nur in abstrakten Klassen deklariert werden.
  • Modifikatoren

    Situation

    public

    default

    protected

    private protected

    private

    erreichbar für nicht-Subklasse aus dem gleichen Paket?

    ja

    ja

    ja

    nein

    nein

    erreichbar für Subklasse aus dem gleichen Paket?

    ja

    ja

    ja

    nein

    nein

    erreichbar für nicht-Subklasse aus einem anderen Paket?

    ja

    nein

    nein

    nein

    nein

    erreichbar für Subklasse aus einem anderen Paket?

    ja

    nein

    nein

    nein

    nein

    geerbt von Subklasse in gleichem Paket?

    ja

    ja

    ja

    ja

    nein

    geerbt von Subklasse in einem anderen Paket?

    ja

    nein

    ja

    ja

    nein

    Superklassen, Objekte und Klassenhierarchie

    Jede Klasse, die definiert wird, besitzt eine Superklasse. Wenn die Superklasse nicht in der extends-Klausel angegeben ist, so ist die Superklasse implizit Object. Object ist die einzige Klasse, die keine Superklasse besitzt. Methoden, die von Object definiert werden, können von jedem Java-Objekt aufgerufen werden.
    Weil jede Klasse eine Superklasse besitzt, formen Klassen in Java eine Klassenhierarchie, die als Baum mit Object als Wurzel dargestellt werden kann.

    Subklassen-Konstruktoren

    Aufrufen eines Konstruktors aus der Superklasse:

    Das Schlüsselwort super dient dazu, die Konstruktor-Methode der Superklasse aufzurufen.
    Der Konstruktoraufruf der Superklasse muß als 1. Anweisung innerhalb der Konstruktor-Methode erscheinen.
    Wenn die 1. Anweisung in einem Konstruktor nicht ein explizter Aufruf des Konstruktor der Superklasse mit super ist, dann fügt Java implizit den super()-Aufruf ein:

    Weil der Superklassen-Konstruktor immer zuerst aufgerufen wird, wird immer als erstes der Object-Konstruktor aufgerufen, gefolgt von der Subklasse und der Klassenhierarchie hinunter zu der Klasse, die instanziert wurde.
    Ist kein Konstruktor in einer Klasse deklariert, wird der Standardkonstruktor aufgerufen, der wiederum nichts anderes macht, als den Superklassenkonstruktor aufzurufen.


    Abstrakte Klasssen und Schnittstellen

    Eine abstract-Methode in Java entspricht in etwa einer "rein virtuellen" Funktion in C++, d.h. eine virtuelle Funktion, die als = 0 deklariert ist. Javaklassen, die abstract-Methoden enthalten, können nicht instanziert werden. Ist eine Methode abstract definiert, muß sie nicht implementiert werden.

    Regeln für abstract-Methoden und abstract-Klassen:

    Schnittstellen

    In Java dürfen Klassen nur eine Superklasse besitzen, das bedeutet, daß die von C++ bekannte Mehrfachvererbung nicht möglich ist. Statt dessen kennt Java die sogenannten Interfaces. Das sind reine Schnittstellen, die keinerlei Implementierungen enthalten.
    Eine Schnittstelle sieht aus wie eine abstrakte Klasse, außer, daß sie das Schlüsselwort interface statt den Wörtern abstract und class benutzt.
    Alle Methoden in einer Schnittstelle sind implizit abstract. Jede Variable, die in einer Schnittstelle deklariert ist, muß static und final sein .
    Eine Klasse kann mit dem Schlüsselwort implements eine oder mehrere Schnittstellen vererben. Diese Klasse erbt alle Konstanten und die abstrakten Methoden. Die Methoden müssen dann überschrieben werden.

    Beispiel:

    Schnittstellen erweitern

    Schnittstellen können Subschnittstellen besitzen. Eine Subschnittstelle erbt alle abstrakten Methoden und Konstanten seiner Superschnittstelle und kann neue abstrakte Methoden und Konstanten definieren.
    Eine Schnittstelle, die mehr als eine Schnittstelle erweitert, erbt alle abstrakten Methoden und Konstanten aller Schnittstellen und kann neue abstrakte Methoden und Konstanten definieren.
    Eine Klasse, die solch eine Schnittstelle implementiert, muß alle abstrakten Methoden, die in der Schnittstelle selbst definiert sind, und alle Methoden, die von allen Superschnittstellen geerbt wurden, implementieren.



    ... [ Seminar WWW und JAVA] ... [ Thema Überblick über die Sprache Java ] ... [ Vergleich C++/Java ] ... [ Klassenbibliotheken ] ...