
Lernen Sie, was Java ist, welche grundlegenden Eigenschaften Java besitzt. Das sind Objektorientierung, Übersetzung der Programmcodes zu so genanntem Bytecode und dessen Ausführung in einer virtuellen Java-Maschine.
In dieser Lektion erfahren Sie, wie und wo Sie die erforderlichen Programme für die Entwicklung und Ausführung von Java-Programmen beschaffen. Exemplarisch zeige ich Ihnen, wie Sie diese Programme auf Ihrem heimischen Computer installieren.
Die Windows-Installation unterscheidet sich ein wenig von derjenigen, wie sie bei macOS funktioniert. Sehen Sie, wie Sie das JDK sowie auch Eclipse unter Windows installieren.
Für Ubuntu 16.04 zeige ich, wie Sie das JDK von Oracle installieren.
Das erste Java-Programm wird mit einem einfachen Texteditor erstellt. Übersetzung und Aufruf des Programms erfolgen im Terminalfenster. Sie erfahren den grundlegenden Aufbau eines Java-Programms. Außerdem erlernen Sie den grundsätzlichen Umgang mit den Java-Entwicklungswerkzeugen.
Nicht immer kann ein Programmcode problemlos übersetzt werden. Lernen Sie Fehlermeldungen des Java-Compilers kennen. Unter Windows verwenden Kommandozeile und grafische Benutzeroberfläche unterschiedliche Zeichensatzkodierungen. Das hat unschöne Auswirkungen. Sehen Sie sich diese Auswirkungen an und ergreifen Sie entsprechende Maßnahmen.
In dieser Lektion erlernen Sie den grundsätzlichen Umgang mit Eclipse. Außerdem zeige ich Ihnen, wie Sie Ihre Programme bequem und effizient mit javadoc kommentieren können.
Das Seminar wurde mit Java 9 aufgenommen. Jetzt gibt es Java 10. - Kein Problem: Hier zeige ich Ihnen, wie Sie Java 10 mit Eclipse nutzen.
Um in Programmen Daten speichern zu können, brauchen Sie Variablen. Diese haben jeweils einen bestimmten Datentypen. In Java gibt es 8 primitive Datentypen. Ich stelle Ihnen diese Datentypen vor und erläutere Ihnen die darauf definierten Operationen.
In diesem Video zeige ich Ihnen, wie Sie die Theorie über Variablen und Datentypen in die Praxis umsetzen. D.h., es werden Variablen mit unterschiedlichen Datentypen implementiert und die darauf definierten Operationen vorgeführt. Dabei gibt es einiges zu beachten!
Nicht alle Zeichen lassen sich einfach über die Tastatur eingeben. Manche Zeichen haben in Java auch eine besondere Bedeutung. Was ist wie zu tun, wenn Sie solche Zeichen in Ihren Programmen verwenden wollen? - Diese Lektion zeigt Ihnen, wie das geht. Stichwort: Escape-Sequenzen.
Zeichenketten werden vielfältig und häufig in Programmen verwendet. Der entsprechende Datentyp heißt in Java String. Ein String ist kein primitiver Datentyp, ein String ist ein Objekt. Er ist jedoch so tief und fest in Java verankert, dass wir ihn leicht verwenden können. Es gibt aber dennoch einiges zu beachten. Da sind z.B. der Vergleich auf Gleichheit und andere Dinge mehr, die es zu beachten gilt.
Programme sollen interaktiv mit dem Anwender kommunizieren, der Anwender soll Daten zur Verarbeitung in ein Programm eingeben können. In diesem Video zeige ich Ihnen ein "Kochrezept", wie Sie einfache Eingaben in Java realisieren können.
Nicht immer wollen Sie Daten interaktiv eingeben. Auch die Angabe der zu verarbeitenden Daten in Form von Kommandozeilenargumenten ist eine Möglichkeit, Programmen Daten zu übergeben. Sehen Sie in diesem Video wie das funktioniert. Informell lernen Sie auch bereits, was Arrays sowie Wrapper-Klassen sind.
Logische Ausdrücke sind oftmals zusammengesetzte Ausdrücke. Aussagen/Bedingungen werden mit UND und/oder ODER verknüpft. Freilich gibt es weitere Operatoren zur logischen Verknüpfung. In diesem Video zeige ich Ihnen, wie man diese Operatoren verwendet und wie sie wirken. Wir wiederholen hier auch die Grundlagen der Aussagenlogik. Die werden Sie brauchen, wenn Sie später komplexe Bedingungen zur Steuerung von Verzweigungen oder Wiederholungen formulieren müssen.
Zur Überprüfung Ihres Lernerfolgs stelle ich Ihnen drei Aufgaben. Die Musterlösungen erfahren Sie in den kommenden zwei Lektionen.
Vorstellung der Musterlösungen zu den ersten zwei Aufgaben.
Vorstellung der Musterlösung zur dritten Aufgabe.
Die Informatik kennt drei grundlegende Konstrukte zur Programmabaufsteuerung: Sequenz, Verzweigung und Wiederholung
Mit Hilfe der if-else-Verzweigung realisieren wir Verzweigungen mit einer oder auch zwei alternativen Programmabläufen.
Mit Hilfe von Konstanten gestalten wir den Programmcode übersichtlicher und machen ihn leichter wartbar.
Neben der if-else-Verzeigung kennt Java einen weiteren Verzweigungstyp. Das ist die switch-case-Anweisung.
Der ternäre Operator sieht ein wenig seltsam aus, kann aber in besonderen Situationen ein if-else-Statement mit einer trefflich kurzen Formulierung ersetzen.
Die for-Schleife ist eine kopfgesteuerte Schleife, die immer dann gerne verwendet wird, wenn die Anzahl der Wiederholungen abzählbar ist.
Verschiedene arithmetische Ausdrücke lassen sich in einer prägnanten Kurzschreibweise notieren. Ich zeige Ihnen, wie diese Kurznotation aussehen und funktionieren.
Die while-Schleife ist neben der for-Schleife die zweite Schleifenform in Java, die kopfbesteuert ist.
Die dritte Schleifenform in Java ist die do-while-Schleife, eine fußgesteuerte Schleife.
Nicht immer wollen wir alle Anweisungen stehen, die in einer Schleife stehen auch ausführen. Gelegentlich wollen wir vorzeitig einen neuen Schleifendurchlauf initiieren oder auch eine Schleife abbrechen. break und continue stellen uns dies Möglichkeiten zur Verfügung.
Wenn wir in Java etwas programmieren, was einen Fehler hervorrufen kann, können wir dies ausprobieren (try). Im Fehlerfall wird eine Ausnahme geworfen, die wir auffangen können (catch), um den Fehler zu behandeln.
Was sind Methoden, wie sind sie aufgebaut? - Unsere erste eigene Methode empfängt keinerlei Parameter und gibt auch keinen Wert zurück. Sie zeichnet eine Linie.
Methoden können Parameter empfangen, um ihnen Werte zu übergeben und/oder eine Methode zu steuern. Außerdem können Methoden Werte zurückliefen.
In Java gibt es lediglich Wertübergaben bei der Übergabe von Argumenten an die Parameter von Methoden. Was das bedeutet, wird in diesem Video analysiert und vorgeführt.
Methoden können sich selbst rekursiv aufrufen. Viele Aufgabenstellungen sind rekursiv formuliert, sie lassen sich mittels Rekursion elegant lösen. Außerdem wollen wir, quasi ergänzend, mit Ausnahmen arbeiten, um unsere Methodenaufrufe abzusichern.
Rekursiven sind oftmals naheliegend und ebenso oft auch sehr elegant. Grundsätzlich sollten wir uns bei allen Implementierungen, die wir vornehmen, nach deren Laufzeitverhalten fragen. Die rekursive Implementierung der Fibonacci-Folge ist ein Parade-Beispiel dafür, auf der einen Seite elegant zu sein, jedoch leider auch ein ebenso schlechtes Laufzeitverhalten zu besitzen.
Fehlerbehandlung mit Hilfe von Ausnahmen (Exceptions) am Beispiel der rekursiven Falkultätsberechnung.
Java gestattet es uns, Methoden zu überladen. Das bedeutet, für unterschiedliche Methoden den gleichen Methodenbezeichner verwenden zu dürfen. System.out.println() ist ein Paradebeispiel für eine überladene Methode. Das können wir auch mit unseren eigenen Methoden realisieren.
Nutzen Sie die Übungsaufgaben, um Ihr erworbenes Wissen zu überprüfen. Wie bei den vorangegangenen Übungsaufgaben lernen Sie auch wieder etwas Neues hinzu.
In dieser Lektion werden die Syntax von Arrays und deren grundlegenden Eigenschaften erläutert. Die folgenden Videos befassen sich dann mit typischen Array-Anwendungen.
Eine typische Anwendung von Arrays mit Zahlenwerten ist die Vektor- und Matrixrechnung. Hier zeige ich die Multiplikation zweier NxN-Matrizen.
Zeichenketten werden intern als Arrays von Zeichen gespeichert. Lernen Sie in diesem Video, wie zwei Zeichenketten miteinander verglichen werden, um festzustellen, ob beispielsweise Zeichenkette 1 größer, kleiner oder gleich Zeichenkette 2 ist. Derartige Vergleich werden regelmäßig benötigt, wenn sie Zeichenketten alphabetisch sortieren wollen.
Das Sieb des Eratosthenes ist ein Algorithmus, um Primzahlen zu ermitteln.
Es gibt viele Dinge, die wir sammeln können, wie z.B. Sammelbilder. In dieser Lektion schreiben wir ein Programm, welches das Sammlerproblem simuliert. Wieviele Bildchen müssen wir kaufen, um beispielsweise ein Sammelalbum vollständig zu füllen? Wieviele Bilder haben wir am Ende doppelt?
Das Suchen von Daten ist eine der häufigsten Anwendungen in der täglichen Praxis. In diesem Video betrachten wir die lineare Suche.
Wenn die zu durchsuchenden Daten sortiert sind, können wir die binäre Suche verwenden. Sie stellt stellt den schnellsten denkbaren Suchalgorithmus dar.
Der BubbleSort ostleicht zu verstehen und entsprechend einfach zu implementieren. Leider ist er für die Praxis untauglich, auch wenn viele Seminare den BubbleSort als Sortierverfahren (ohne adäquate Alternative) vorstellen. Hier erfahren Sie, wie der BubbleSort funktioniert. Sie lernen aber auch blitzschnelle Alternativen kenn und zu nutzen.
In dieser Übung lernen Sie eine weitere Anwendungsmöglichkeit von Arrays kennen.
Musterlösung zum Self-Avoiding-Walk.
Musterlösung zur Maus im Labyrinth (Backtracking)
Musterlösung zum Josephus-Problem
Kurze Vorstellung dessen, was Sie im Rahmen der objektorientierten Programmierung erwartet und wir wir vorgehen werden, um die Möglichkeiten der Objektorientierung für uns in Java zu erschließen. Mini-Projekt: Datum, Person, Student
Packages sind physikalisch Verzeichnisse im Dateisystem. Klassen könne nur innerhalb dieses Verzeichnisses sichtbar sein oder aber öffentlich sichtbar sein (public).
Eine Klasse ist quasi ein Bauplan. Von diesem Bauplan können wir Instanzen/Objekte erzeugen. Dazu brauchen wir einen Konstruktor, der beschreibt, wie ein Objekt einer Klasse erzeugt wird.
Java stellt uns einen Standard-Konstruktor zur Verfügung. Der ist aber in den seltensten Fällen das, was wir uns wünschen. Also definieren wir uns eigene Konstruktoren.
Mit Hilfe von Zugriffsmodifizierern können wir die Attribute, die Instanz- und Klassenvariablen einer Klasse, vor unbefugten Zugriffen schützen und ihre Sichtbarkeit einschränken.
Ein Konstruktor muss sicherstellen, das nur valide Objekte erzeugt werden.
Objekte können nicht mit dem doppelten Gleichheitszeichen auf inhaltliche Gleichheit verglichen werden, weil es sich eben um Objekte handelt. Um einen inhaltlichen Vergleich durchzuführen, müssen wir die von Object ererbte Methode equals() überschreiben. Üblicherweise ist auch die Methode hashCode() zu überschreiben.
Jede Klasse erbt von der Klasse Object eine Methode toString() geerbt. Diese wird genutzt, wenn Objekte ausgegeben werden sollen. Wenn sie geeignet überschrieben wird, können wir eigene Objekte adäquat ausgeben.
Um Objekte zuweisen zu können und sie dabei zu kopieren, gibt es verschiedene Möglichkeiten. Die erste Möglichkeit ist die Verwendung eines Kopierkonstruktors. Der Sorte Kopierkonstruktor, den wir implementieren arbeitet auf einem Objekt, dessen Instanzvariablen ausschließlich primitive Datentypen sind.
Die Methode clone() stellt in vielen Situationen eine Alternative zum Kopierkonstruktor dar, wenn ein Objekt vervielfältigt werden soll.
Wenn Objekt Instanzvariablen besitzen, die selbst Objekte sind, müssen wir bei deren Initialisierung Obacht geben, die zur Initialisierung übergebenen Objekte zu kopieren. Dazu brauchen wir Kopierkonstruktoren, wie sie in Folge 61 erstmalig vorgestellt wurden.
Obgleich Springs Objekte sind, brauchen wir nicht explizit einen Kopierkonstruktor aufrufen, wenn wir Instanzvariablen mit ihnen initialisieren. String erfahren in Java eine Sonderbehandlung, die ihre Handhabung bequemer gestaltet.
Wenn wir Objekt haben, die andere Objekte als Instanzvariablen besitzen, dann müssen wir eine Tiefenkopie (deep copy) anfertigen.
Wenn Objekte Instanzvariablen besitzen, die von einem Referenzdatentypen sind, müssen wir beim Vergleich darauf achten, ihre inhaltliche Gleichheit zu prüfen.
Wie auch bei den Konstruktoren, müssen wir Obacht geben, wenn unsere Methoden Objekte beinhalten und wir deren Werte ändern oder zurückgeben wollen.
Altersberechnungen können unbequem sein. In Java ist das mit Hilfe der Klasse ChronoUnit aber einfach.
Vererbung beschreibt die Spezialisierung einer Klasse.Eine abgeleitete Klasse kann zusätzliche Attribute und Methoden definieren. Ererbte Methoden können überschrieben werden.
Im Gegensatz zu Instanzvariablen und -methoden, gibt es Klassenmethoden, Klassenkonstanten und Klassenvariablen nur einmal im Rahmen der Klassen. Instanzen können auf diese zugreifen. Umgekehrt gilt das jedoch nicht. Eine Klassenmethode kann beispielsweise keine Instanzvariablen ansprechen.
Die Klasse Student ist noch nicht fertig. Ergänzen Sie weitere Konstruktoren, machen Sie die Klasse vergleichbar und implementieren Sie eine Methode clone(), damit der Student vervielfältigt werden kann.
Implementierung der fehlenden Methoden der Klasse Student.
Klassen können so allgemein definiert werden, dass es nicht möglich ist und/oder keinen Sinn macht, ihre Methoden auszuimplementieren (abstrakte Klassen). Sie können aber die Ausgangsklasse für abgeleitete Klassen bilden.
Möchte die Vererbung verhindern, so können Klassen finalisiert werden. Sie können dann nicht mehr beerbt werden. Soll eine Klasse zwar vererbt werden können, jedoch Teile vor Veränderung geschützt werden, so könne auch nur Teile einer Klasse finalisiert werden.
Weil jedes Objekt immer auch vom Typ seiner Elternklasse ist, können wir diese Eigenschaft nutzen, um verschiedene Objekttypen, die Mitglied eines gemeinsamen Teils der Klassenhierarchie sind, gemeinschaftlich zu handhaben.
Viele Autoren behaupten, Java besitze keine Zeiger. Das ist falsch. Immer wenn wir mit Objekten arbeiten, arbeiten wir mit Zeigern. Allerdings werden Sie in Java üblicherweise als Referenzen bezeichnet und verschiedene Manipulationen, wie sie beispielsweise in C/C++ gestattet sind, sind in Java aus Sicherheitsgründen nicht möglich. Ungeachtet dessen, können wir Referenzen im Sinne von Zeigern verwenden.
Als Beispiel verpacken wir das letzte Beispiel, den Abzählreim, in eine Jar-Datei.
Die einfach verkettete Liste ist eine der einfachsten Datenstrukturen. An ihr lassen sich bereits viele Dinge lernen, die wir später, beim Stack oder der Queue, wieder benötigen.
Implementierung einer einfach verketteten Liste mit Hilfe von Referenzen (Zeigern). Die entsprechende Klasse implementiert das im vorigen Video definierte Interface.
Wir schreiben ein kleines Programm, welches die vorher implementierte Liste verwendet.
Im Gegensatz zur einfach verketteten Liste, kann eine doppelt verkettete List auch rückwärts durchschritten werden. Implementieren Sie eine solche Liste.
Ich stelle Ihnen eine Musterimplementierung zur doppelt verketteten Liste vor.
Enumerationen stellen eine verallgemeinerte Art und Weise dar, durch Aufzählungen zu iterieren.Listen können als Aufzählungen interpretiert werden, weshalb wir eine Enumeration für unsere Listen implementieren wollen.
Bis hierhin haben wir Generizität dadurch hergestellt, die Nutzlast unserer Klassen als Object zu definieren. Das ist "Old School". Unsere Datentypen, wie beispielsweise die Listen, sind zwar für beliebige Datentypen als Nutzlast verwendbar, der Java-Compiler kann jedoch keine Typsicherheit garantieren. Deshalb wurden in Java die so genannten Generics eingeführt. Dabei handelt es sich um eine typischer Generizität.
Der Stack ist ein in der Informatik häufig gebrauchter abstrakter Datentyp.
Immer, wenn wir eine Reihenfolge umkehren wollen, können wir das mit Hilfe eines Stücks erledigen. Das ist besonders dann nützlich, wenn die Daten(Struktur), die wir umkehren wollen, dies selbst nicht bewerkstelligen kann. So können wir unter Verwendung eines Stacks, auch eine einfach verkettete Liste in umgekehrter Reihenfolge ausgeben.
Eine einfach verkettete Liste lässt sich auf unterschiedliche Weise implementieren. Eine Möglichkeit ist die, ein Paar Stacks dazu zu verwenden. - Der Stack ist eine vielseitig einsetzbare Datenstruktur.
Ein Stack ist, neben viele weiteren Anwendungen, gut geeignet, um einen Infix-Ausdruck nach Postfix zu konvertieren.
Warteschlangen werden für Simulationen genutzt, finden aber auch beim Traversieren von Bäumen Anwendung, wenn wie beispielsweise einen Baum ebenenweise ausgeben wollen.
Implementieren Sie eine Warteschlange mit Hilfe eines Arrays.
Vorstellung der Musterlösung - Quellcode im Begleitmaterial.
Vorstellung des ADT Tree.
Wir bauen einen ganz einfachen binären Baum mit Hilfe von verzeigerten Knotenelementen. Wir starten mit dem Interface und der Definition eines Knotens.
Unser Baum wird mit Hilfe von Referenzen implementiert. Dabei werden unsere Knoten aus dem vorangegangenen Video passen zusammengefügt, um letztlich einen Baum abzubilden.
Mit Hilfe der definierten Konstruktoren bauen wir einen Baum für einen arithmetischen Ausdruck auf.
Wir schreiben eine Klasse, die es uns ermöglicht einen Baum in den verschiedenen Traversierungen auszugeben.
Die Tiefensuche entspricht einer Preorder-Traversierung eines Baumes. Sie arbeitet jedoch nicht rekursiv, sondern verwendet einen Stack.
Mit Hilfe der Breitensuche können wir einen Baum ebenenweise ausgeben. Dazu verwenden wir eine Queue.
Wir lesen einen Postfix-Ausdruck ein und generieren daraus dynamisch einen entsprechenden Baum.
Bislang haben wir die Elemente unserer Bäume direkt im Rahmen einer Traverse ausgegeben. Wir wollen jetzt eine Enumeration schreiben, die uns die Elemente unseres Baumes in der gewünschten Reihen zurückgibt.
Dieses Java-Seminar gibt sich nicht damit zufrieden, Ihnen die Syntax von Java beizubringen. Vielmehr geht es darum, Ihnen die Grundlagen der praktischen Informatik am Beispiel von Java zu vermitteln. D.h., es werden elementare Datenstrukturen und Algorithmen (Kellerspeicher (Stack), Schlangen (Queue), Bäume (Tree) vermittelt sowie das Suchen und Sortieren oder das Vergleichen von Zeichenketten und vieles andere mehr. Sie lernen eine Vielzahl von Algorithmen und Datenstrukturen, die Sie dann auch in der Java-Dokumentation wiederfinden, so dass Sie in die Lage versetzt werden, diese zu verstehen und selbstständig zu nutzen.
Anhand ausgesuchter Übungsaufgaben und Musterlösungen lernen Sie den vermittelten Stoff in praktische Programme umzusetzen. Alle Übungsaufgaben sind grundsätzlich so gestaltet, dass Sie bei deren Lösung zusätzliches Wissen erlangen. Das setzt ein gewisses Maß an Eigeninitiative voraus! - Zu allen Übungsaufgaben gibt es Musterlösungen.
Sie lernen alle erforderlichen Grundlagen, um selbstständig Programme entwerfen und erfolgreich implementieren zu können.