uio--WebPageMain-Module

JAVA-B1 Klassen public class instance System.out.println() {@link Klasse} {@param Klasse} getClass().getSimpleName() extends Objekte Interfaces FAQ classes Erweitern von Klassen mit extends finale Konstanten (@see Finalisierung von Klassen ) Polymorphismus Nested Classes @Override Annotation innere Klassen lokale Klassen anonyme Klassen Lamda Expressions FAQ Nested Classes

Klassen im Detail Overview return-Statements return & void return bei primitiven Typen return bei Objekten return-Statements von Methoden mit/ohne return Rückkehr ohne return Rückkehr über return throws Exception Kopie oder Referenz Covariant Return Types this this mit Objekt-Feldern this mit Methoden und im Konstuktor Zugriffsmodifikatoren public protected private Class Member static public static final PI Initialisierung Initialisierung von Feldern Initialisierung von Klassenfeldern Static Block Lambda-Expressions Methoden-Referenzen

Enumerationen und enum-Types Enumerationskonstanten Enumerationen mit Werten Samstag/Sonnabend Example @! Enumerationen FAQ Enum @!Descr/Exmpl/Index

Interfaces Einfache Interfaces (Marker) Interfaces mit Methoden Default-Methoden static Interfaces FAQ Vererbung / Inheritance Vererbung / Inheritance super Keyword method-overriding-and-hiding hiding-of-fields object-as-superclass Finalisierung Finale Klassen und Methoden Finale Methoden Finale Utility-Klasse "IdGenerator" "Template-Methode"-Pattern DataProcessor process(){ r(), p(), w() } Composition-over-Inheritance abstract Abstrakte Klassen und Methoden Beispiel Abstrakte Klassen und Methoden abstract Implementierungsklassen FAQ Vererbung Kein this in super(..) Verhindern Überschreiben von Membern

Generics Generische Programmierung Generische Typparameter Generische Klassen Generische Interfaces Generische Methoden Generische Felder Generische Collection (ArrayList) Diamond Operator Generische Arrays Example Beispiel "GenerischerSpeicher" Ring-Speicher-Algorithus mit generischem Array Beispiel: GenerischePerson mit Berufsgruppe Beispiel: Berufsgruppe mit Static/Non-Static Nested Classes

Modularisierung Package Overview Package Structure Package Info

Modules Overview Setup Setup Module Info

Java New Features Java 8+ Java Record Record Syntax Record Demo Herkömmliche POJOs Lösung mit Records Records Zusammenfassung

INDEX

Finalisieren

Finalisieren | Klassen und Methoden

In diesem Themenblock befassen wir uns mit dem Schreiben finaler Klassen und Methoden sowie Verfahren, wie man ab JAVA 17 Klassen und Methoden versiegeln kann, diesen Schutz aber für ausgewählte Klassen aber wiederum erlauben kann.

Das Finalisieren und Schützen von Klassen und Methoden ist insbesondere für Utility-Klassen sowie für Methoden zweckmäßig, welche direkt aus Konstruktoren aufgerufen werden.

Beispiel

JAVA-B1 | Beispiel

Prinzip

Finalisieren | Prinzip

Man kann in JAVA manche oder auch alle Methoden einer Klasse mit Hilfe des Keywords final als «final» deklarieren. Die entsprechenden Member können in Unterklassen nicht mehr überschrieben werden.

Bereits die Klasse java.lang.Object hat einige finalisierte Methoden.

Tipp: Immer dann, wenn man Methoden hat, deren Implementierung auf keinen Fall verändert werden sollte, weil anderenfalls der Zustand eines Objekts inkonsistent werden können, ist es anzuraten, diese Methoden mit final zu finalisieren.

Im Schach beginnt immer weiß

Beispiel: Im Schachspiel gibt es zwei Farben für die zwei Spieler, weiß und schwarz. Um sicherzustellen, dass auch ein von ChessAlgorithm abgeleite Klasse auf keinen Fall die getFirstPlayer() Methode überschreiben kann, lässt sich diese als final derklarieren.


 
class ChessAlgorithm {
 enum ChessPlayer { WHITE, BLACK }
 ...
 final ChessPlayer getFirstPlayer() {
 return ChessPlayer.WHITE;
 }
 ...
}

 

Anmerkung: Member ohne das Keyword public gelten in JAVA als public, in C# .NET aber als privat.

enum ChessPlayer: JAVA ermöglicht nicht nur innere Klassen sondern auch innere Enumerationen.

Quelle: https://docs.oracle.com/javase/tutorial/java/IandI/final.html

Finale Utility-Klassen

Finalisieren | Finale Utility-Klassen

Ein beliebtes Entwurfsmuster sind Utility-Klassen, welche weder instanziiert noch erweitert werden sollen.

Das nachfolgende Beispiel zeigt eine Klasse, welche in einer Anwendung dazu dient, auf Anfrage jeweils eine neue ID als Nummer als String «ID-0» bis «ID-n» zu erzeruegen.


 
package com.stuelken.java.b1.finalization;

/**
 * Finale Klasse welche nicht erweitert werden kann und von welcher darüber
 * hinaus in diesem Fall auch keine Objekte erzeugt werden können.
 * 
 * @author t2m
 */
public final class IdGenerator {

	/**
	 * Ein Zähler für alle vom {@link IdGenerator} erzeugten IDs.
	 */
	private static int counter = 0;

	/**
	 * Privater Konstruktor zu Verhinderung einer Instanziierung von Objekten.
	 */
	private IdGenerator() {
	}

	/**
	 * Ein synchronisierte, Thread-sichere Methode, welche eine neue ID generieren
	 * kann.
	 * 
	 * @return
	 */
	public static synchronized String next() {
		return "ID-" + (++counter);
	}

	/**
	 * Testprogramm
	 * 
	 * @param args Keine Parameter
	 */
	public static void main(String[] args) {
		System.out.println(IdGenerator.next());
		System.out.println(IdGenerator.next());
	}
}

 

Klasseneigenschaften

Mit private static int counter wird eine private Klasseneigenschaft deklariert. Damit diese einen Startwert beim Programmstart hat, wird dieses Feld mit 0 initialisiert.

Privater Konstruktor

Mit private IdGenerator() { } wird verhindert, dass man Objekte dieser Klasse wie sonst üblich mit dem new Keyword erstellen kann, dann da der Konstruktor privat ist, ist eine Adresse dieser Methode von außen nicht mehr möglicht. Der Konstruktor kann also nur noch immer der Klasse selbst adressiert werden.

Thread-Safe

public static synchronized String next() ist nun eine öffentliche Klassenmethode, bereits synchronisiert für den Fall, dass diese Methode auch bei nebenläufiger Programmierung zum Einsatz kommen soll. Mit next() wird ein String «ID-» gefolgt vom int-Wert von counter geliefert.

Diese Klasse ist also «Thread-Safe».

Klassenmethoden adressieren

System.out.println(IdGenerator.next()); zeigt, wie man die statische Methode nun aufrufen kann, ohne ein Objekt dieser Klasse erzeugen zu können.

Finalisierte Klassen

public final class * { } bewirkt, dass die Klasse auch außerhalb des Package verwendet werden kann, eine Erweiterung der Klasse und damit eine Subklasse ist wegen final allerdings nicht möglich.

Template-Methode-Pattern

Finalisieren | Template-Methode-Pattern

Ein beliebtes Entwurfsmuster ist das Template-Methode-Pattern.

Um die Reihenfolge der Ausführung von Methoden und auch die Verfügbarkeit von Methoden in Objekten abgeleiter Klassen sicherzustellen und gleichzeitig verhindern zu können, dass jemand die zentrale Superklasse als Vorgabe verändert, definiert man die Superklasse abstrakt, schafft für die Reihenfolge von Methoden eine Template-artige finale Methode, die nicht überschrieben werden kann, und ermöglicht dann Entwicklern die Programmierung von Subklassen als Implementierungsklassen.


 
public abstract class DataProcessor {
 // Template-Methode: feste Abfolge der Verarbeitungsschritte
 public final void process() {
 readData();
 processData();
 writeData();
 }
 
 // Abstrakte Hook-Methoden, die in Unterklassen spezifiziert werden.
 protected abstract void readData();
 protected abstract void processData();
 protected abstract void writeData();
}

public class CSVDataProcessor extends DataProcessor {

 @Override
 protected void readData() {
 System.out.println("CSV-Daten werden gelesen...");
 }

 @Override
 protected void processData() {
 System.out.println("CSV-Daten werden verarbeitet...");
 }

 @Override
 protected void writeData() {
 System.out.println("CSV-Daten werden geschrieben...");
 }
}

// Demo-Klasse
public class TemplateMethodDemo {
 public static void main(String[] args) {
 DataProcessor processor = new CSVDataProcessor();
 processor.process();
 }
}


 

Template-Method-Pattern

Das Template-Method-Pattern nutzt eine finale Methode, die eine feste Reihenfolge an Aufrufen ("Schablone") definiert und sogenannte "Hooks" (abstrakte oder optionale Methoden) anbietet, die spezifisch implementiert werden können.

Reihenfolge der zu implementierenden Methoden

Die finale Methode process() stellt das fest definierte Vorgehen dar. Da man diese Methode nicht überschreiben kann und die abstrakten deklarierten Methoden sicherstellen, dass eine erweiterte Subklasse diese Methoden haben wird, kann schlussendlich jedes Objekt, welches über eine Implementierungsklasse erzeugt wurde, diese Methoden in der richtigen Reihenfolge ausführen.

Implementierung durch Unterklassen

Spezifische Details wie das Einlesen oder Verarbeiten der Daten werden in den Unterklassen implementiert. Der maßgebende oft benutzte Begriff ist Implementierungsklasse oder Implementierung einer abstrakten Methode.

Konsistente API

So wird eine konsistente API geschaffen, die dennoch erweiterbar bleibt.

Template-Methode-Pattern

Finalisieren | Composition over Inheritance

Wenn fast alle Methoden final sind, ist es oft sinnvoller, Komposition statt Inheritance zu nutzen.

In einem Beispiel zeigen wir, wie man Klassen durch Einbetten von Objekten kombiniert, statt von diesen Klassen erben zu wollen.


 
// Beispiel einer Komponente
public class Engine {
 public void start() {
 System.out.println("Motor gestartet.");
 }
 public void stop() {
 System.out.println("Motor gestoppt.");
 }
}

// Klasse, die eine Engine als Teil ihrer Zusammensetzung (Composition) enthält
public class Car {
 private Engine engine;
 
 public Car() {
 this.engine = new Engine();
 }
 
 public void drive() {
 engine.start();
 System.out.println("Das Auto fährt.");
 engine.stop();
 }
}

// Demo-Klasse
public class CompositionDemo {
 public static void main(String[] args) {
 Car car = new Car();
 car.drive();
 }
}


 

Klasseneigenschaften

Anstatt von der Engine-Klasse zu erben, wird hier eine Engine als Attribut innerhalb des Car-Objekts genutzt. Dies fördert lose Kopplung, erhöht die Flexibilität und vermeidet starre Vererbungsstrukturen.

Prinzip der Delegation

Dieses Entwurfsmuster kennt man in einer Abwandlung als das Prinzip der Delegation.

FootNotes, Keywords, Tags


    Hinweise, Rechte, Marken

    UI ORGANIZED.

    UIO3 Es ist einfacher als Du denkst.

    Stelle noch heute Deine Anfrage.

    uio--WebPageFooter-Module