Einführung in Java Design Patterns (Software Entwurfsmuster)

prog Java Programmieren Lernen Leave a Comment

In objektorientierten Programmiersprachen werden Design Patterns verwendet, um ein ganz bestimmtes Software-Entwurfsproblem zu lösen. Das Design Pattern (Entwurfsmuster) dient dabei als eine Art Rezept, mit dessen Hilfe die gegebene Programmieraufgabe gelöst wird.

In Java wird mittels Design Pattern das Zusammenspiel von Klassen, Interfaces, Objekten und Methoden mit dem Ziel beschrieben, vordefinierte Lösungen für konkrete Programmierprobleme anzubieten. Die Entwurfsmuster sind wohlüberlegte Designvorschläge, die Software-Entwickler für den Entwurf ihren eigenen Anwendungen nutzen können.

In Java werden die folgenden Entwurfsmuster häufig verwendet:

  1. Das Singleton (Das Einzelstück) Design Pattern
  2. Das Immutable (Das Unveränderliche) Design Pattern
  3. Interfaces (Schnittstellen) in Java
  4. Das Iterator (Zugriffszeiger) Design Pattern
  5. Das Delegate (übertragen) Design Pattern

Die Entstehungsgeschichte von Design Patterns


Mehr Infos auf Amazon

Der breiten Öffentlichkeit wurden Design Patterns im Jahr 1995 vorgestellt. Die vier Autoren Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides gelten als Wegbereiter dieser revolutionären Software-Entwurfsidee. Sie haben in ihrem Buch Design Patterns. Elements of Reusable Object-Oriented Software oft benötigte Lösungsmuster für wichtige Programmierprobleme allgemein beschrieben.

Mit ihrem Werk über Software-Entwurfsmuster haben sie eine der bedeutsamsten und hilfreichsten Entwicklungen der objektorientierten Programmierung der späten 90er losgetreten und es überhaupt erst ermöglicht standardisierte Bezeichnungen für bestimmte Softwaredesigns zu finden. Seit dem Erscheinen ihrer Buchs werden Begriffe wie Singleton, Factory oder Iterator routinemäßig von Programmieren bei der Beschreibung von objektorientierten Softwareprojekten verwendet und förderten die Kommunikationsfähigkeit der Entwickler untereinander erheblich.

In diesem Beitrag möchten wir die wichtigsten Java Design Patterns kurz vorstellen. Dabei werden wir auf die grundlegenden Eigenschaften des jeweiligen Entwurfsmusters eingehen und mögliche Einsatzgebiete vorstellen. Da Design Patterns ein sehr komplexes Thema sind, können wir mit diesem Beitrag nicht auf alle Details eingehen, daher sind unsere Ausführungen als Einstieg in dieses spannende Gebiet zu sehen.

Read More

Enumerations – Die Aufzählungstypen von Java

prog Java Programmieren Lernen 3 Comments

In diesem Beitrag behandeln wir die Aufzählungstypen (Enumerations) in Java. Mit der fünften Version von Java wurden Enumerations in den Kern der Programmiersprache eingebaut.

Gleichzeitig wurde das neue Schlüsselwort enum eingeführt. Mit dem neuen Schlüsselwort enum werden in Java eigene Aufzählungstypen definiert. Die Syntax ist, wie an folgendem Beispiel zu erkennen ist, sehr einfach und intuitiv:

Auf die definierten Werte des Aufzählungstyps wird über Typname.WertA zugegriffen. Diese können einer Variablen vom Typ der Enumeration zugewiesen werden, etwa folgendermaßen: Typname variableX = Typname.WertA;.

In Java sind Aufzählungstypen als Klassen realisiert. Die definierten Werte sind als Objekte implementiert. Daraus ergeben sich die folgenden nützlichen Eigenschaften:

  • Der Name der Werte kann mit Hilfe der toString-Methode im Klartext ausgegeben werden.
  • Mit Hilfe der equals-Methode kann auf Gleichheit geprüft werden.
  • Enumerations können in switch-Anweisungen verwendet werden.
  • Die beiden Interfaces Comparable und Serializable sind für Aufzählungen implementiert.
  • Mit Hilfe der values-Methode wird ein Array zurückgegeben, das alle Elemente der Enumeration enthält. In Verbindung mit der erweiterten for-Schleife können die Elemente sehr einfach durchlaufen werden.
  • Mit EnumSet und EnumMap wurden zwei neue Collection-Klassen eingeführt, die das Arbeiten mit Enumerations-Mengen erleichtern.

Read More

Autoboxing und Autounboxing in Java

prog Java Programmieren Lernen 1 Comment

In diesem Beitrag stellen wir das automatische Ein- und Auspacken (Autoboxing und Autounboxing) von primitiven Datentypen aus Wrapper-Klassen vor.

Eine Wrapper-Klasse kapselt die jeweilige primitive Variable in einem sehr einfachen Objekt. Dabei stellt die Wrapper-Klasse einige Methoden für den Zugriff auf die primitive Variable und nützliche Funktionen zur Verfügung. Wer mehr über Wrapper-Klassen erfahren möchte, kann dies in unserer Einführung in Wrapper-Klassen tun.

Der Mechanismus des Autoboxing und Autounboxing wurde in Java 5 eingeführt. Mit Autoboxing und Autounboxing wird das Verfahren bezeichnet, mit dessen Hilfe automatisch zwischen primitiven Datentypen und Wrapper-Objekten konvertiert wird.

In der Praxis sieht das dann so aus: Einer Methode, die als Argument einen primitiven Datentypen erwartet, kann auch der entsprechende Wrapper-Datentyp übergeben werden. Erwartet die Methode bspw. einen float-Wert, kann ihr auch ein Float-Objekt übergeben werden. Der übergebene Wert wird automatisch konvertiert, falls dies erforderlich ist.

Read More

Einführung in Wrapper-Klassen in Java

prog Java Programmieren Lernen 4 Comments

In diesem Beitrag werden wir Wrapper-Klassen behandeln und eine kleine Einführung in dieses spannende Thema geben. Wir stellen die Wrapper-Klassen am Beispiel der vordefinierten Klassen für das leere Objekt void und die 8 primitiven Datentypen in Java vor:

Datentyp Größe [Bit] Standardwert Wertebereich Wrapper-Klasse
boolean 1 false true, false java.lang.Boolean
byte 8 0 -128 … +127 java.lang.Byte
short 16 0 -215 … 215-1 java.lang.Short
int 32 0 -231 … 231-1 java.lang.Integer
long 64 0 -263 … 263-1 java.lang.Long
float 32 0.0 ±1.2×10−38 … ±3.4×1038 java.lang.Float
double 64 0.0 ±2,2×10−308 … ±1.8×10308 java.lang.Double
char 16 \u0000 ‘\u0000′ … ‘\uFFFF’ java.lang.Character
void - - - java.lang.Void

Eine Wrapper-Klasse kapselt die jeweilige primitive Variable in einem sehr einfachen Objekt. Dabei stellt die Wrapper-Klasse einige Methoden für den Zugriff auf die primitive Variable und nützliche Funktionen zur Verfügung.

Read More

Interfaces (Schnittstellen) in Java

prog Java Programmieren Lernen 2 Comments

Wir behandeln in diesem Beitrag die wichtigsten Eigenschaften vom Interfaces in Java.

Dabei soll dieser allgemeine Beitrag über Interfaces als Übersicht dienen. Ausführliche Erklärungen zu den einzelnen Themen findet ihr in den jeweiligen Themenbeitrag:

Was ist ein Interface in Java?

In Java kann eine abgeleitete Klasse nur genau eine Vaterklasse haben. Das Erben von mehr als einer Superklasse (Mehrfachvererbung) ist nicht möglich.

Den Entwicklern der Programmiersprache Java war Mehrfachvererbung bekannt und auch die Nachteile die sie mit sich bringt. Ganz auf Mehrfachvererbung verzichten wollten sie aber nicht und schafften einen Mittelweg: das Interface.

Interfaces können als Ersatzkonstrukt für Mehrfachvererbung gesehen werden. Eine Klasse kann mehrere Interfaces implementieren, d.h. ihr können mehrere Schnittstellen zur Verfügung gestellt werden. Jede dieser Schnittstellen (Interfaces) muss aber von der Klasse vollständig implementiert werden.

Read More

Vererbung und Polymorphismus in Java

prog Java Programmieren Lernen 1 Comment

In Java können mit Hilfe der Vererbung Programmteile wiederverwendet werden, dabei werden die Merkmale bereits vorhandener Klassen auf abgeleitete Klassen übertragen. Unser Beitrag Vererbung in Java – Ableiten einer Klassen behandelt die Grundlagen der Vererbung.

Das Konzept der Vererbung ist in Java auf Einfachvererbung begrenzt, das heißt eine neue Klasse kann maximal von einer anderen Klasse abgeleitet werden. Andere objektorientierte Programmiersprachen verfügen über die Möglichkeit der Mehrfachvererbung, bei der eine Klasse von mehreren Klassen abgeleitet werden kann. Da dies aber auch Probleme mit sich bringt, wurde in Java nur die Einfachvererbung implementiert.

Es gibt in Java aber durchaus das Konzept der Mehrfachvererbung. Und zwar wurde mit Hilfe der Interfaces eine restriktive Art der Mehrfachvererbung geschaffen.

Überlagern von Methoden und dynamisches Binden in Java

In Java werden Methoden der Vaterklasse an die abgeleiteten Klassen vererbt. Die vererbten Methoden können dann in den abgeleiteten Klassen neu definiert werden. Dieser Vorgang wird in Java als das Überlagern von Methoden bezeichnet.

Zusätzlich können in den Tochterklassen neue Methoden definiert oder die geerbten Methoden unverändert übernommen werden. Somit können in einer abgeleiteten Klasse drei Arten von Methoden vorhanden sein:

  • In der Tochterklasse definierte neue Methoden
  • Von der Vaterklasse geerbte unveränderte Methoden
  • Von der Vaterklasse geerbte überlagerte Methoden, die in der Tochterklasse neu definiert wurden

Wurde eine Methode überlagert (d.h. in der abgeleiteten Klasse neu definiert), wird beim Aufrufen der Methode auf Objekten dieses Datentyps immer die überlagerte Version verwendet.

Vererbung von Konstruktoren und Destruktoren in Java

In Java werden Konstruktoren nicht vererbt, daher müssen in einer abgeleiteten Klasse alle erforderlichen Konstruktoren erneut definiert werden. Dabei kann mit Hilfe des Schlüsselworts super auf die Konstruktoren der Vaterklasse (Superklasse) zugegriffen und dadurch bereits vorhandener Quellcode wiederverwendet werden.

Interessierte können mit unserem Beitrag über die Vererbung von Konstruktoren und Destruktoren in Java tiefer in die Materie eintauchen.

Konstruktorenverkettung in Java

Wird in Java ein neues Objekt instanziert, dann wird dabei immer der zu dem verwendeten new-Operator passende Konstruktor aufgerufen. Welcher Konstruktor der Passende ist, wird von den angegebenen Parametern entschieden.

Bei dem Aufruf des passenden Konstruktors wird auch immer der Konstruktor der Vaterklasse (Superkonstruktor) aufgerufen. Dies geschieht entweder implizit oder explizit, wenn der Entwickler einen aufzurufenden Superkonstruktor festlegt. Diese Vorgabe muss in der ersten Anweisung eines jeden Konstruktors erfolgen.

Polymorphismus und Konstruktoren in Java

Polymorphe Methodenaufrufe können in Konstruktoren zu schwerwiegenden Programmfehlern führen, die sehr schwierig zu lokalisieren sind.

Aufgrund der Initialisierungsreihenfolge von Konstruktoren besteht die Gefahr, dass Variablen der abgeleiteten Klasse noch nicht initialisiert wurden, die polymorph aufgerufenen überlagerten Methoden diese Variablen jedoch schon verwenden.

Daher sollten Aufrufe von Methoden, welche möglicherweise in Subklassen überlagert werden, nicht in Konstruktoren erfolgen. Zur Veranschaulichung habe wir eine Beispielanwendung für polymorphe Methodenaufrufe in Konstruktoren erstellt, bei der eine unvollständige Variableninitialisierung auftritt.

Die Initialisierungsreihenfolge von Konstruktoren sollte jedem Java-Entwickler bestens bekannt sein. Wir behandeln sie in unserem Beitrag: Konstruktoren und Destruktoren in Java ausführlich, an dieser Stelle soll uns aber die folgende kurze Beschreibung genügen.

In Java werden bei jeder Instanzierung die folgenden beiden Schritte ausgeführt:

  1. Die Konstruktoren der Vaterklassen werden aufgerufen (von der eigenen Klasse bis hoch zur Urklasse object). Dabei werden die Variablen der Vaterklassen initialisiert und anschließend die Anweisungen in den Vaterklassen-Konstruktoren ausgeführt.
  2. Danach werden die Variablen der eigenen Klasse initialisiert und die Anweisungen des eigenen Konstruktors ausgeführt.

Wird nun in einem Konstruktor einer Vaterklasse eine Methode aufgerufen, die in einer abgeleiteten Klasse überlagert wurde, sind zu diesem Zeitpunkt die Variablen der Klasse noch nicht initialisiert. Dies würde erst später in Schritt 2 erfolgen, wenn der Konstruktor der abgeleiteten Klasse ausgeführt wird.

In unserem nächsten Beitrag behandeln wir das spannende Thema: Interfaces (Schnittstellen) in Java. Interfaces können als Ersatzkonstrukt für Mehrfachvererbung gesehen werden. Eine Klasse kann mehrere Interfaces implementieren, d.h. ihr können mehrere Schnittstellen zur Verfügung gestellt werden. Jede dieser Schnittstellen (Interfaces) muss aber von der Klasse vollständig implementiert werden.

Der folgende Link führt euch zurück zum Programmierkurs für Java-Beginner.

Klassen in Java: Die Grundlagen der objektorientierten Programmierung

prog Java Programmieren Lernen 1 Comment

In der Programmiersprache Java besitzen Klassen eine sehr große Bedeutung. Sie sind die Baupläne nach denen Objekte (Instanzen von Klassen) modelliert werden. Wir behandeln in diesem Beitrag die wichtigsten Eigenschaften vom Klassen in Java.

Dabei soll dieser allgemeine Beitrag über Klassen und Methoden als Übersicht dienen. Ausführliche Erklärungen zu den einzelnen Themen findet ihr in den jeweiligen Themenbeitrag:

Was ist objektorientierte Programmierung?

Objektorientierte Programmierung ermöglicht eine natürliche Modellierung, erhöht die Effizienz des Entwicklers durch Wiederverwendbarkeit der Programmelemente und vermindert die Komplexität der Anwendungen durch Abstraktion und Kapselung.

Durch Abstraktion wird zwischen Konzept und Umsetzung unterschieden, d.h. es gibt ein Objekt und einen Bauplan nach dem dieses Objekt modelliert wird. Klassen sind Baupläne nach denen Objekte modelliert werden.

Read More

Verzweigungen in Java: Die if-else-Anweisung, switch-Anweisung und assert-Anweisung

prog Java Programmieren Lernen 1 Comment

In Java werden Verzweigungs-Anweisungen für das Ansteuern bestimmter Programmbereiche verwendet. Dazu werden vor Laufzeitbeginn Bedingungen festgelegt, unter denen bestimmte Programmbereiche ausgeführt werden oder auch nicht.

Zur Laufzeit wird dann an diesen Verzweigungen überprüft, ob die jeweilige Bedingung erfüllt ist oder nicht. Ist die Bedingung erfüllt, wird der verzweigte Programmbereich ausgeführt. Falls nicht, wird der Programmbereich übersprungen, also ausgelassen.

In der Programmiersprache Java sind die einfachen if-Anweisung, die if-else-Anweisung und die switch-Anweisung für Mehrfachverzweigungen implementiert. In unserem Beitrag Verzweigungen – Die if-else-Anweisung und die switch-Anweisung werden die verschiedenen Verzweigungsanweisungen in Java ausführlich mit einer Beispielanwendung vorgestellt.

Die assert-Anweisung in Java

Mit Assertions können vom Programmierer logische Behauptungen aufgestellt werden, von denen er ausgeht diese seien wahr. Solange das Programm korrekt funktioniert, bleiben die assert-Anweisungen unbemerkt. Sobald mit Hilfe einer Assertion aber ein Programmfehler aufgedeckt wird, wird eine Ausnahme des Typs AssertError ausgelöst.

In Java werden assert-Anweisungen immer dann eingesetzt, wenn man den Zustand des Programms überprüfen und diesen durch bestimmte Annahmen verifizieren möchte. Wie das Ganze in der Praxis aussieht, könnt ihr in unserem Beitrag Wie man mit assert-Anweisungen Java-Programme zuverlässiger und besser lesbar machen kann.

Die Überprüfung des Programmzustands könnte man auch mit if-Anweisungen vornehmen. Dann wäre aber nicht auf den ersten Blick zu erkennen, dass es sich bei dieser Überprüfung um eine Verifizierung des Programmzustands handelt, da if-Anweisungen vorwiegend zur Steuerung des Programmablaufs eingesetzt werden. Assertions helfen somit den eigenen Quellcode lesbarer zu gestalten.

In unserem nächsten Beitrag geben wir eine Einführung in die Grundlagen der objektorientierten Programmierung in Java. Dabei stellen wir Klassen, Methoden, Konstruktoren und Destruktoren vor und wie sie in Java richtig verwendet werden.

Der folgende Link führt zurück zum Programmierkurs.

Schleifen in Java: Die while-Schleife, do-while-Schleife, for-Schleife und erweiterte for-Schleife

prog Java Programmieren Lernen 1 Comment

Möchte man in Java bestimmte Programmabschnitte wiederholt ausführen lassen, sind dafür Schleifen genau das richtige Programmierwerkzeug. In Java werden dem Entwickler seit Version 1 drei unterschiedliche Schleifenarten zur Verfügung gestellt. In Java 5 wurde mit der erweiterten for-Schleife eine vierte Schleifenart hinzugefügt.

In Java sind die folgenden Schleifenarten implementiert:

  • Die while-Schleife
  • Die do-while-Schleife
  • Die for-Schleife
  • Die erweiterte for-Schleife

Um für den jeweiligen Anwendungsfall die passende Schleifenart auszuwählen, müssen die Besonderheiten der Schleifen bekannt und verstanden sein. Wir stellen in dem Beitrag Die while-Schleife, do-while-Schleife und for-Schleife in Java die drei bekannten Schleifenarten vor und zeigen wann welche Schleifenart gewählt werden sollte.

Die erweiterte for-Schleife in Java

In Java 5 (JDK 1.5) wurde mit der erweiterten for-Schleife eine weitere Schleifenart eingeführt. Die erweiterte for-Schleife kann in Java benutzt werden, um den Quelltext kompakter und lesbarer zu machen. Mit ihr kann das einmalige Durchlaufen aller Listenelemente von Anfang bis zum Ende ausgeführt werden. Manche Programmierer kennen diese Schleifensonderform auch als “foreach”-Variante.

Der Hauptgrund für das Einführen der erweiterten for-Schleife war, dass mit ihrer Hilfe effektiver auf speziellen Datenstrukturen wie Arrays und Collection zugegriffen werden kann. Für diese allgemeinen Aufgaben ist die erweiterte for-Schleife hervorragend geeignet. Für Sonderfälle sollte aber weiterhin die normale for-Schleife verwendet werden.

In dem Beitrag Die erweiterte for-Schleife in Java stellen wir die erweiterte for-Schleife ausführlich vor und gehen mit einem Anwendungsbeispiel auf ihre besonderen Eigenschaften ausführlich ein.

In unserem nächsten Beitrag behandeln wir Verzweigungen in Java: Die if-else-Anweisung, switch-Anweisung und assert-Anweisung. Verzweigungs-Anweisungen werden in Java für das Ansteuern bestimmter Programmbereiche verwendet. Dazu werden vor Laufzeitbeginn Bedingungen festgelegt, unter denen bestimmte Programmbereiche ausgeführt werden oder auch nicht.

Zur Laufzeit wird dann an diesen Verzweigungen überprüft, ob die jeweilige Bedingung erfüllt ist oder nicht. Ist die Bedingung erfüllt, wird der verzweigte Programmbereich ausgeführt. Falls nicht, wird der Programmbereich übersprungen, also ausgelassen.

Mit folgendem Link gelangt ihr zurück zum Java-Kurs.

Operatoren, Ausdrücke und Anweisungen in Java

prog Java Programmieren Lernen 1 Comment

In Java gibt es vier elementare Anweisungen, die leere Anweisung, Block-Anweisung, Ausdrucks-Anweisung und Variablendeklaration. Eine Anweisung ist ein Befehl, der von der Anwendung ausgeführt wird. Dies kann die Deklaration einer Variable oder auch das Aufrufen einer Methode sein.

Es ist sogar möglich der Anwendung eine leere Anweisung zu geben. In diesem speziellen Fall besteht die Anweisung nur aus einem Semikolon. Mehr über Anweisungen erfahrt ihr in unserem Beitrag: Einführung in die elementaren Anweisungen in Java

Ausdrücke und Operatoren in Java

Mit Hilfe von Ausdrücken werden Variablen Werte zugewiesen, logische Bedingungen genküpft und numerische Berechnungen durchgeführt. Die Zusammensetzung von Ausdrücken ist exakt festgelegt. Sie bestehen immer aus Operatoren und Operanden, auf die Operatoren angewendet werden.

Ein Beispiel für einen Ausdruck: gehaltNetto = gehaltBrutto - abgaben;.

In Java wird zwischen den folgenden 6 verschiedenen Operatortypen unterschieden:

Für Programmierer ist das korrekte Verständnis der Operatortypen sehr wichtig, da sie die elementaren Bestandteile des Quellcodes sind. Daher sollten Programmieranfänger sich nicht scheuen mit den verschiedenen Operatortypen zu experimentieren.

Die Rangfolge der Java-Operatoren

Die Operatoren werden in Java nach einer genau definierten Reihenfolge ausgewertet. Operatoren eines höheren Ranges bekommen vor Operatoren niedrige Ränge Vorrang. Diese Spracheigenschaft wird als Vorrangregel oder Bindungsregel bezeichnet.

In Java besitzt jeder Operator eine bestimmte Bindungskraft. So besitzt bspw. der Multiplikations-Operator eine höhere Bindungskraft als der Additions-Operator und wird demnach in Ausdrücken zuerst ausgewertet. Wie die einfache mathematische Regel: Punktrechnung vor Strichrechnung.

In manchen Fällen besitzen Java-Operatoren die gleiche Bindungskraft also den gleichen Rang, dann entscheidet ihre Assoziativität über die Auswertungsreihenfolge. So besitzen der Additions- und Subtraktions-Operator alleine gesehen die gleiche Bindungskraft.

Werden sie aber in einer Kette von Additionen und Subtraktionen verwendet, bestimmt ihre Assoziativität über die Auswertungsreihenfolge. In diesem Fall sind beide Operatoren linksassoziativ, daher wird der Ausdruck von links nach rechts ausgewertet.

Daher wird a + b - c wie (a + b) - c ausgewertet und nicht wie a + (b - c).

Eine ausführliche Auflistung aller Java-Operatoren und ihre Rangfolge untereinander könnt ihr in unserem Beitrag: Rangfolge der Java-Operatoren finden.

In unserem nächsten Beitrag Schleifen in Java: Die while-Schleife, do-while-Schleife, for-Schleife und erweiterte for-Schleife stellen wir die vier Schleifenarten von Java vor. Schleifen werden benötigt, um in Java bestimmte Programmabschnitte wiederholt ausführen zu lassen.

Der folgende Link führt zurück zum Programmierkurs für Java Anfänger.