04.07 Weitere Modifizierer

Sie kennen bereits die Sichtbarkeitsmodifizierer und wissen, wie Sie mit static umgehen müssen. In Java existieren aber noch weitere Modifizierer – abstract, final, native, strictfp, synchronized, transient und volatile – deren Verwendung Sie in diesem Kapitel (mit Ausnahme von abstract, welches in einem eigenen Kapitel behandelt wird) kennen lernen.

final

Das Schlüsselwort final wird verwendet, um Code-Elemente als unveränderbar zu markieren. final ist aber nicht gleich final. Das Verhalten von final unterscheidet sich durch das Element, welches als final deklariert wird.

  • Primitive Datentypen
final int i = 23;

… dürfen nicht verändert werden. Folgendes ist also unzulässig

i = 42;

und endet in einem Compiler-Fehler.

  • Objekte
final StringBuffer buff = new StringBuffer();

… dürfen manipuliert (Aufruf von Methoden, verändern von Attributen, …) aber nicht neu angelegt werden. Folgendes ist also zulässig

buff.append("Manipulation");

Wohingegen dieses

buff = new StringBuffer("Neu Anlegen");

ebenfalls in einem Compiler-Fehler endet.

  • Klassen
public final class FinalClass {}

… die diesen Modifizierer zugewiesen bekommen, dürfen nicht beerbt werden. Folgendes ist also unzulässig

public class SubFinalClass extends FinalClass {}

und endet selbstverständlich wieder in einem Compiler-Fehler.

  • Methoden
public class FinalTest {
  public final void finalMethod() {}
}

… dürfen nicht überschrieben werden. Auch dieser Code

public class SubFinalTest extends FinalTest {
  public void finalMethod() {}
}

endet folglich in einem Compiler-Fehler.

final wird für die unterschiedlichsten Möglichkeiten eingesetzt. Diese wären u. a.:

  • Um Überschreiben oder Verändern von Attributen, Klassen und Methoden zu verhindern
  • Um Performance zu gewinnen, da der Compiler dadurch in der Regel auf die dynamische Methodensuche verzichten kann
  • Um lokale Variablen in lokalen Klassen sichtbar zu machen (siehe 04.10 Innere Klassen)
  • Um Konstanten einer Klasse/eines Objekts in der Form public (static) final int SOMETHING = 1; zu definieren

Wenn Sie einem finalen Attribut bei der Initialisierung noch keinen Wert zuweisen, so müssen Sie dies spätestens im Konstruktor, oder im (statischen) Initialisierer erledigen.

public class AClass {

  private final int xyz;

  public AClass(int value) {
    this.xyz = value;
  }
}

native

Dieser Modifizierer wird ausschließlich für Methoden verwendet. Methoden, die als native deklariert wurden, haben keinen Methoden-Körper sondern bestehen nur aus der Methoden-Signatur, einem Rückgabetyp und einem Sichtbarkeitsmodifizierer. Deshalb werden sie auch mit einem Semikolon abgeschlossen.

public native double calcSomethingNative(double val1, double val2);

Hinter jeder als native deklarierten Methode steckt eine nativ, also Betriebssystem abhängig, ausgelagerter Funktion in einer entsprechenden Programm-Bibliothek (z. B. .dll bei Windows), welche aufgerufen wird. Ist dies nicht der Fall, kommt es natürlich zu einem Fehler. Sie lernen im JNI Kapitel mehr über native Methoden.

strictfp

Dieses Schlüsselwort für Klassen und Methoden erzwingt, dass alle Operationen mit Fließkommazahlen innerhalb ihres Gültigkeitsblock nach der einfachen Darstellung laut IEEE 754 verarbeitet werden, welche besagt, dass alle Zahlen mit einfacher Genauigkeit (float) 32 Bit, und alle mit doppelter Genauigkeit (double) 64 Bit groß sind. Diese Vorgehensweise wurde bis Java 1.1 standardmäßig angewandt. Seit Java 1.2 wird mit der erweiterten Darstellung (sofern von der Hardware/vom System unterstützt) nach IEEE 754 gearbeitet, welche min. 43 bzw. 79 Bit für die selben Datentypen reserviert. Um diese Gegebenheit zu umgehen wurde strictfp eingeführt.

public strictfp class StrictFPClass {}

public strictfp double calcStrictFp(double d1, double d2) {
  return d1 * d2;
}

Die erweiterte Darstellung bietet bei Systemen, die selbige unterstützen, folgende Vorteile:

  • Größere Genauigkeit bei Rechenoperatoren
  • Höhere Performance, da nicht zwischen einfacher und erweiterter Darstellung konvertiert werden muss

Durch die größere Genauigkeit der erweiterten Darstellung kann es allerdings dazu kommen, dass die selben Rechenoperatoren auf unterschiedlichen Systemen unterschiedliche Ergebnisse liefern.

Für Sie als Programmierer hat ein float aber weiterhin immer 32 Bit und ein double immer 64 Bit. Die erweiterte Darstellung kommt lediglich intern zur Laufzeit des Programms während Rechenoperatoren zur Geltung.

synchronized

Unterschiedliche Threads können eine Methode parallel aufrufen. Um dies zu verhindern, muss diese Methode mit dem Schlüsselwort synchronized versehen werden. Führen Sie zur Veranschaulichung folgenden Code aus:

public class SyncTest {

  public static void main(String[] args) {

    new Thread(new Runnable() {
      public void run() {
        printSynchronized("Thread 1");
      }
    }).start();
    new Thread(new Runnable() {
      public void run() {
        printSynchronized("Thread 2");
      }
    }).start();
    new Thread(new Runnable() {
      public void run() {
        printNormal("Thread 3");
      }
    }).start();
    new Thread(new Runnable() {
      public void run() {
        printNormal("Thread 4");
      }
    }).start();
  }

  public static synchronized void printSynchronized(String print) {
    System.out.println("Print synchronized Start: " + print);
    try {
      Thread.sleep(5000);
    }
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Print synchronized End: " + print);
  }

  public static void printNormal(String print) {
    System.out.println("Print normal Start: " + print);
    try {
      Thread.sleep(5000);
    }
    catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("Print normal End: " + print);
  }
}

Es ist nicht weiter schlimm, wenn Sie obigen Code nicht verstehen. Er soll Ihnen nur die Verwendung von synchronized demonstrieren. Weitere Informationen zu Threads finden Sie später im entsprechenden Kapitel.

transient

Variablen, die als transient deklariert wurden, werden beim Speichern eines Objekts nicht mit gespeichert. Wird das Objekt also wieder geladen, erhält sie den zugewiesenen Standardwert. Hierzu lernen Sie mehr im Kapitel über ObjectStreams.

transient int i = 23;

volatile

Auch dieses Schlüsselwort steht wieder im Zusammenhang mit Threads. Threads können eigene Kopien von Variablen halten, wodurch es passieren kann, dass unterschiedliche Threads mit unterschiedlichen (veralteten) Variablenwerten arbeiten. Mit volatile zwingen Sie die Virtual Machine dazu, vor jedem Zugriff auf diese Variable den Wert zu synchronisieren.

volatile int volI = 42;
Previous Article
Next Article

7 Replies to “04.07 Weitere Modifizierer”

  1. spinatwachtel

    Das hier scheint mir logisch nicht ganz schlüssig (beidesmal IEEE 754):
    „Dieses Schlüsselwort für Klassen und Methoden erzwingt, dass alle Operationen mit Fließkommazahlen innerhalb ihres Gültigkeitsblock nach der einfachen Darstellung laut IEEE 754 verarbeitet werden, welche besagt, dass alle Zahlen mit einfacher Genauigkeit (float) 32 Bit, und alle mit doppelter Genauigkeit (double) 64 Bit groß sind. Diese Vorgehensweise wurde bis Java 1.1 standardmäßig angewandt. Seit Java 1.2 wird mit der erweiterten Darstellung (sofern von der Hardware/vom System unterstützt) nach IEEE 754 gearbeitet, welche min. 43 bzw. 79 Bit für die selben Datentypen reserviert. „

  2. spinatwachtel

    strictfp und der Abschnitt dazu.
    War das jetzt verständlich? Ganz so viel Text ist auf dieser Seite ja nicht und den Abschnitt habe ich auch noch zitiert…

  3. spinatwachtel

    Das hier:
    „.. IEEE 754 verarbeitet werden, welche besagt, dass alle Zahlen mit einfacher Genauigkeit (float) 32 Bit..“
    im Vergleich zu:
    „..Seit Java 1.2 wird mit der erweiterten Darstellung (sofern von der Hardware/vom System unterstützt) nach IEEE 754 gearbeitet, welche min. 43 bzw. 79 Bit für ..“
    Hat sich die IEEE 754 hier geändert, oder ist es bei einem Teil einfach eine andere Nummer?

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.