C.1 Objektorientierung C.1.3 final-Modifikator Ein gegensätzliches Konzept zum abstract-Modifikator stellt das Schlüsselwort final dar. Hiermit verhindert man bei der Deklaration von Methoden und Attributen, dass diese von erbenden Klassen überschrieben werden können. Das bedeutet, dass erbende Klas- sen diese Methoden oder Attribute weiterhin besitzen, jedoch müssen sie die geerbte Va- riante übernehmen und können sie nicht überschreiben. Es ist sogar möglich, Klassen als final zu definieren. Das führt dazu, dass von dieser Klasse nicht mehr geerbt werden kann, eine andere Klasse kann also die finale Klasse nicht mehr erweitern. Ein Beispiel hierfür ist die die Standard-Klasse String. Somit ist es nicht mehr möglich, eine eigene String-Klasse zu schreiben, die von der Standard-String-Klasse erbt. Auch in Blöcken kann final bei Variablen verwendet werden. Dies hat zur Konsequenz, dass nach erst- maliger Zuweisung eines Wertes keine weiteren Zuweisungen mehr durchgeführt werden. Auf diese Weise werden auch Konstanten in Java realisiert: 1 public class Mensch 2 16 17 public static void main(String[] args) 21 } C.1.4 Interfaces In Java ist es nicht möglich, von mehreren Klassen zu erben. Die Entscheidung, auf Mehr- fachvererbung zu verzichten, wurde von den Java-Entwicklern wohl überlegt getroffen, da Mehrfachvererbung nicht nur komplex und damit fehlerträchtig ist, sondern auch schnell zu ungewollten Mehrdeutigkeiten führen kann. Als Ersatz dafür ist es in Java dafür möglich, mehrere Interfaces zu implementieren, womit die fehlende Mehrfachvererbung sinnvoll ausgeglichen wird. Interfaces sind abstrakte Definition von Methoden, die ein Klasse im- plementieren muss, um dem Interface gerecht zu werden. Damit sind Interfaces vergleich- bar mit abstrakten Klassen, die nur abstrakte Methoden enthalten, mit der Ausnahme, dass Klassen eben mehrere Interfaces implementieren, und nicht nur eine Klasse erweitern kön- nen. Während man bei erbenden Klassen von einer ist-ein-Beziehung spricht, entspricht das Implementieren von Interfaces einer verhält-sich-wie-Beziehung. Ein Interface steht also für bestimmte Eigenschaften und Merkmale, für die es aufgrund der vorgegebenen Methoden steht. Anders als bei abstrakten Klassen lassen sich bei Interfaces keine Metho- den direkt implementieren, die Interfaces definieren lediglich die Methodensignatur und 73.
[Audio] Wir werden im zweiten Slide dieser Präsentation über den finalen Modifier in Java weiterführende Konzepte und abstrakte Konzepte behandeln. Diese abstrakten Konzepte beziehen sich auf implizite Konzepte, die nicht explizit deklariert werden müssen. Ein Beispiel dafür sind Interfaces. Zum Beispiel möchten wir in Java Studentenausweise und Girokonten modellieren. Obwohl es sich um verschiedene Objekte handelt, haben sie dennoch gemeinsame Eigenschaften. Hier können wir ein Interface verwenden, das wie folgt aussieht: [zeige Folie mit dem Interface Konto]. Das Interface kann mehrere Methoden definieren. Die Klassen, die das Interface implementieren möchten, müssen die Methode "erfrageWert" besitzen, aber es ist ihnen überlassen, welchen Code sie dafür verwenden möchten, solange die Signatur mit der im Interface angegebenen übereinstimmt. Dadurch wird sichergestellt, dass alle implementierenden Klassen eine Möglichkeit bieten, den Wert zu erfragen. [zeige Code-Beispiel mit der Implementierung des Interfaces in der Klasse GiroKonto]. Die Klasse GiroKonto besitzt die Methode "erfrageWert", wie es vom Interface gefordert wird. Eine Klasse, die das Interface implementiert, muss diese Methode ebenfalls besitzen, ansonsten würde es zu einem Compilerfehler führen. Sie fragen sich vielleicht, wie das Interface Konto in unsere beiden Klassen passt, die grundlegend unterschiedliche Objekte darstellen. Aber auch hier kann das Interface nützlich sein, denn auch die Klasse StudentenAusweis implementiert das Interface Konto, um dem Interface gerecht zu werden. [zeige Code-Beispiel mit der Implementierung des Interfaces in der Klasse StudentenAusweis]. Die Klasse StudentenAusweis hat ebenfalls die Methode "erfrageWert", obwohl sie anders aufgebaut ist als die Klasse GiroKonto. Das zeigt, wie flexibel und hilfreich Interfaces in der Java-Programmierung sein können. Damit sind wir am Ende dieses Slides angekommen und können zum nächsten Thema übergehen..
[Audio] "Die Variable j wird durch die Methode intValue() in int umgewandelt. Dies ermöglicht die Anwendung von Methoden wie equals() oder compareTo() auf primitiven Datentypen, ohne dass diese zuvor explizit in Objekte umgewandelt werden müssen. Dieser Vorgang wird als Autoboxing bezeichnet. Ein Beispiel dafür ist die Variable "Max" vom Typ String, die automatisch in ein Objekt umgewandelt und mit dem String "Max" verglichen wird. Dadurch können auch primitive Datentypen von den Methoden von Objekten profitieren. Es ist jedoch wichtig zu beachten, dass die Verwendung von primitiven Datentypen als Objekte die Performance beeinflussen kann aufgrund des höheren Speicherbedarfs. Aus diesem Grund sollte man in bestimmten Fällen überprüfen, ob es notwendig ist, primitive Datentypen als Objekte zu verwenden oder ob die Verwendung von primitiven Datentypen ausreichend ist. Das Autoboxing ist auch nützlich bei der Verwendung von internen Klassen, die auf Attribute und Methoden ihrer umschließenden Klasse zugreifen können. Ein Beispiel dafür ist die innere Klasse Inner, die auf die Variable count der äußeren Klasse Outer zugreift. Normalerweise würde dies zu einem Compilerfehler führen, da count ein primitiver Datentyp ist. Durch die Autoboxing-Funktion wird dieser jedoch automatisch in ein Objekt umgewandelt, um auf die Methode getCount() zugreifen zu können..
[Audio] Willkommen zur vierten Folie der Präsentation über das Thema "Die finale Modifier in Java". Heute sprechen wir über weiterführende Konzepte und den Ausblick in Java. Eine wichtige Neuerung seit Java 5 ist das Autoboxing, welches es dem Programmierer erspart, primitive Datentypen und Wrapper-Typen manuell umzuwandeln. Java übernimmt diese Umwandlung automatisch. Anstatt "Integer y = Integer.valueOf(37)" zu schreiben, können wir einfach "Integer y = 37" verwenden. Jedoch birgt die Verwendung von Wrapper-Klassen eine Gefahr. Wenn wir zwei Integer-Objekte erstellen und ihre Werte vergleichen möchten, werden nicht die Werte, sondern die Referenzen verglichen. Obwohl die Objekte den gleichen Wert speichern, liefern die Vergleichsoperatoren falsche Ergebnisse, da es sich um zwei verschiedene Objekte handelt. Um dieses Problem zu vermeiden, muss die equals() Methode verwendet werden, um die Gleichheit der Objekte zu überprüfen. Es gibt für jeden primitiven Datentyp eine entsprechende Wrapper-Klasse, z.B. Byte, Short, Integer, Long, Double, Float, Boolean, Character und void. Es ist jedoch wichtig, Wrapper-Klassen nur dann zu verwenden, wenn sie wirklich benötigt werden, da bei jeder Erzeugung nicht nur der Wert, sondern auch ein zusätzliches Objekt erstellt werden muss, was die Performance beeinträchtigt. Eine weitere interessante Funktion in Java ist das Enum, welches dazu dient, Aufzählungstypen zu definieren. Zusammenfassend bieten die Verwendung von Wrapper-Klassen und Enums in Java einige Vorteile, jedoch auch Gefahren. Es ist wichtig, diese Konzepte richtig zu verstehen und nur dann zu verwenden, wenn sie notwendig sind. Das war die vierte Folie unserer Präsentation über das Thema "Die finale Modifier in Java". Wir fahren nun mit der fünften Folie fort. Vielen Dank für Ihre Aufmerksamkeit..
[Audio] In Java gibt es einen final Modifier, um Methoden und Attribute davon abzuhalten, von Unterklassen überschrieben zu werden. Aber wie ist es bei Datentypen? Auch hier gibt es eine Lösung: die Verwendung von Enums. Enums erlauben es, eine bestimmte Anzahl von konstanten Werten zu definieren. Zum Beispiel können wir für eine Karte die Farbe (Karo, Herz, Pik oder Kreuz) und den Wert (2 bis 10, Bube, Dame, König oder Ass) festlegen. Anstatt Zahlen als Stellvertreter für die Werte zu verwenden, können wir die Verwendung von Enums nutzen, was einfacher und übersichtlicher ist. Um Enums zu nutzen, müssen wir zuerst die beiden Typen deklarieren, entweder in eigenen Dateien oder innerhalb von Klassen, je nach Projektspezifikationen. Als Beispiel nehmen wir eine Klasse für eine Karte, die die Farbe und den Wert speichert. Hier verwenden wir den final Modifier, um sicherzustellen, dass die Werte nicht verändert werden können. Die Karte-Klasse könnte so aussehen: public class Karte } Nun möchten wir ein komplettes Kartendeck erzeugen. Hierfür nutzen wir die Enums und iterieren über alle möglichen Werte. Mit der Methode values() können wir ein Array mit allen Werten erhalten und somit die Anzahl aller Karten bestimmen. Anschließend erstellen wir für jede Kombination aus Farbe und Wert eine Karte und fügen sie dem Deck hinzu. Karte[] deck = new Karte[Wert.values().length * Farbe.values().length]; int i = 0; for (Wert wert : Wert.values()) } In diesem Beispiel haben wir eine sogenannte foreach-Schleife verwendet, die im nächsten Kapitel genauer erklärt wird. Jeder Wert eines Enums hat neben dem Namen auch einen numerischen Wert, der seiner Position entspricht. Dieser kann mithilfe der Methode ordinal() abgefragt werden. Somit könnten wir den Wert zweier Karten vergleichen, indem wir ihre ordinalen Werte vergleichen..
[Audio] Wir sind jetzt bei Folie 6 von insgesamt 18. Java ist sehr flexibel und vielseitig einsetzbar mit dem final Modifier und Enums. In der Zukunft werden wir uns noch mit weiteren hilfreichen Konzepten beschäftigen. Wir hoffen, Sie konnten einen guten Einblick in die Verwendung des final Modifiers gewinnen. Danke für Ihre Aufmerksamkeit." Die sechste Folie unserer Präsentation behandelt die Verwendung des final Modifiers in Java. Im zweiten Teil werden wir uns mit weiterführenden Konzepten und einem Ausblick beschäftigen. Wie bereits erwähnt, verhindert der final Modifier, dass Methoden und Attribute in Unterklassen überschrieben werden können. Auf Folie 3 haben wir ein Beispiel gesehen, welches dies verdeutlicht. Eine weitere Besonderheit in Java sind Enums, welche objektähnliche Eigenschaften haben und eigene Methoden besitzen können. Wir werden dies anhand eines Beispiels erklären, bei dem ein Enum für verschiedene Farben erstellt werden soll. Üblicherweise werden Farben in Java über die RGB-Werte definiert, aber im Web werden oft Hexadezimalzahlen verwendet. Daher haben wir einen Konstruktor für das Enum erstellt, welcher die RGB-Werte als Parameter entgegennimmt und mithilfe der toHex() Methode den entsprechenden Hex-Wert ausgibt. Dies wird durch die Unterstützung von Generics ermöglicht, welche seit Java Version 5 verfügbar sind und eine generische Programmierung ermöglichen. Wie Sie sehen können, ist Java mit dem final Modifier und Enums sehr vielseitig einsetzbar. In unserem Ausblick werden wir uns noch mit weiteren hilfreichen Konzepten beschäftigen..
[Audio] Folie 7 aus 18 der Präsentation über den finalen Modifier in Java. Der finale Modifier dient dazu, Methoden und Attribute vor Überschreibung durch Unterklassen zu schützen. Neben diesem Konzept gibt es noch weitere fortgeschrittene Konzepte, die sowohl Vorteile bringen als auch die Sicherheit und Fehleranfälligkeit während der Entwicklung verbessern. Eines davon ist die Verwendung von Generics, bei der spezifische Typen für Variablen eingeführt werden. Mit Generics ist es möglich, eine Liste von verschiedenen Datentypen anzulegen, im Gegensatz zu einer Listenklasse, die bisher nur Werte vom Typ int speichern konnte. Wenn wir beispielsweise eine Liste von Namen verwalten wollen, müssen wir unsere bestehende Klasse anpassen. Auch bei anderen Datenstrukturen ist es häufig sinnvoll, eine allgemeinere Containerklasse zu haben, in die verschiedene Datentypen gespeichert werden können. Es könnte verlockend sein, den Datentyp einfach auf Object zu setzen, da in Java jedes Objekt vom Typ Object ist. Allerdings birgt dies einen großen Nachteil, da wir die Kontrolle über den Inhalt unserer Liste verlieren. Wenn wir beispielsweise die Summe aller Elemente in einer Liste von Integer-Werten berechnen wollen, funktioniert dies nicht, wenn der Datentyp auf Object gesetzt ist. Deshalb ist es wichtig, bei der Verwendung von Generics auf die spezifischen Datentypen zu achten. In unserem Beispiel könnten wir die Liste von Integer-Werten anlegen und die Summe aller Elemente berechnen. Es ist zwar möglich, den Datentyp auf Object zu setzen, doch sollte dies nur in Ausnahmefällen geschehen, da es zu unerwarteten Fehlern führen kann..
[Audio] Als erfahrene Programmierer sind Sie wahrscheinlich schon mit dem Konzept der Vererbung vertraut. In Java gibt es jedoch eine Möglichkeit, die Vererbung zu verhindern und Methoden sowie Attribute vor dem Überschreiben durch Unterklassen zu schützen. Dies wird durch den sogenannten final Modifier ermöglicht. Sehen wir uns das genauer an. Auf Folie 8 von 18 sehen Sie einen Code-Ausschnitt, der diese Funktion verdeutlicht. Wie können wir dennoch auf diese Methoden und Attribute zugreifen? Hier kommen die Konzept der Generics ins Spiel. Sie dienen als Platzhalter für den benutzten Typ und werden erst bei der Kompilierung durch einen echten Wert ersetzt. Auf der nächsten Folie sehen Sie die Klasse ListenElement, wo anstatt Object nun T als Platzhalter steht. Auch die Klasse Liste verwendet dieses Konzept, wie Sie auf Folie 10 sehen können. Um ein Objekt vom Typ Liste oder ListenElement zu erzeugen, muss explizit angegeben werden, durch was das T ersetzt werden soll. Ein Beispiel dafür sehen Sie auf Folie 12. Wir hoffen, dass Ihnen dieser Ausblick auf das Konzept der Generics weitergeholfen hat. Lassen Sie uns nun weiter zu den weiterführenden Konzepten gehen..
[Audio] Auf Slide Nummer 9 werden wir uns im Rahmen unseres Vortrags über Java mit dem final Modifier beschäftigen. Dieser Modifier verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können. Wir werden insbesondere das Thema der Datentypen behandeln. In Java gibt es eine Vielzahl von Datentypen, die bereits in unserem Vortrag besprochen wurden. Dennoch gibt es auch fortgeschrittene Konzepte, die es lohnt, genauer zu betrachten. Eines dieser Konzepte sind sogenannte Generics. Sie ermöglichen es uns, Datentypen zu definieren, die erst zur Laufzeit des Programms konkretisiert werden. Dadurch können wir beispielsweise eine Liste von Elementen erstellen, ohne bereits im Voraus zu wissen, welchen Datentyp diese Elemente haben werden. Erst zur Laufzeit, wenn die Liste befüllt wird, wird der Datentyp festgelegt. Ein Beispiel dafür wäre eine Liste von Zahlen, bei der noch nicht bekannt ist, ob es sich um Integer, Double oder andere Datentypen handelt. Diese Entscheidung wird erst während des Befüllens der Liste getroffen. Die Verwendung von Generics bietet jedoch noch weitere Vorteile. Zum einen ermöglicht sie, dass die Datenstrukturen, die in der Java Collections-API zur Verfügung stehen, für beliebige Objekte genutzt werden können. Dazu werden die Objekte einfach als generische Typen deklariert. Zum anderen entfällt durch die Verwendung von Generics das sogenannte "Casting", bei dem Datentypen konvertiert werden müssen. In unserem Beispiel mit der Liste von Zahlen bedeutet das, dass wir nicht mehr auf Integer casten müssen, da die Liste bereits den Datentyp Integer erwartet. Generics können noch viel komplexer genutzt werden, aber an dieser Stelle werden wir nicht näher darauf eingehen. Auf Slide Nummer 9 haben wir uns bereits mit dem Thema Generics beschäftigt. Die Java Collections-API bietet jedoch noch viele weitere nützliche Datenstrukturen, die wir nun genauer betrachten werden. Dazu gehören zum Beispiel Sets, Lists und Maps. Ein Set ist eine Sammlung von Daten ohne Duplikate, vergleichbar mit einer mathematischen Menge. Eine List ist eine geordnete Sammlung von Daten, auf die über einen Positionsindex zugegriffen werden kann. Und eine Map ist eine Sammlung von Schlüssel-Wert-Paaren, wobei jeder Schlüssel eindeutig sein muss. Ein Beispiel für eine Map wäre eine Sammlung von Studentenobjekten, bei der jeder Student eindeutig über eine Matrikelnummer identifiziert werden kann. Wir werden uns nun genauer mit diesen Datenstrukturen befassen und ihre Unterschiede sowie Einsatzmöglichkeiten aufzeigen..
[Audio] Das 'final' Schlüsselwort in Java verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können. In diesem Modul betrachten wir die Verwendung dieses Schlüsselworts in der Java Collections-API. Wir werden Konzepte besprechen und einen Überblick über die folgenden Methoden geben. Mithilfe der gewünschten Eigenschaften der Datensammlung und der vorhandenen Implementierungen können wir konkrete Datenstrukturen auswählen. Zum Beispiel bietet sich für die Speicherung von Studenten mit ihren Matrikelnummern die Verwendung einer Map an. Aber welche Implementierung ist die beste Wahl? Eine TreeMap, HashMap oder LinkedHashMap. Diese Entscheidung hängt von unserem Anwendungsfall ab, da jede Implementierung ihre eigenen Vor- und Nachteile hat. Mit einer HashMap können wir schnell auf einen Datensatz zugreifen, indem wir direkt die Nummer als Hashcode nutzen. Eine TreeMap erfordert hingegen den Durchlauf eines binären Suchbaums, um einen Datensatz zu finden. Dies erfordert einen Aufwand von O(log(n)) bei einer gegebenen Matrikelnummer. Wenn wir jedoch alle Studenten mit Matrikelnummern zwischen 60000 und 70000 auflisten wollen, ist die HashMap nicht geeignet, da sie zuerst alle Schlüssel sammeln und sortieren muss. Die TreeMap ermöglicht dies aufgrund ihrer Baumstruktur einfacher. Eine optimale Wahl ist die Verwendung einer LinkedHashMap, da sie sowohl gehashte Schlüssel als auch eine sortierte und verkettete Liste verwendet. Die Auswahl der richtigen Datenstruktur ist also nicht immer einfach. Zusätzlich zu allgemeinen Datenstrukturen bietet die Java Collections-API auch spezielle Datenstrukturen wie Stacks, Queues und nebenläufige Datenstrukturen an. Außerdem bietet sie eine Vielzahl von Hilfsklassen, die Algorithmen für typische Operationen auf Datenstrukturen bereitstellen. Zum Beispiel beim Kartenspiel. Im nächsten Teil werden wir uns genauer mit diesen Hilfsklassen beschäftigen..
[Audio] Heute werden wir uns mit dem finalen Modifier in Java beschäftigen, der verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können. Als nächstes geht es um weiterführende Informationen zu Datentypen. Eine hilfreiche Funktion der Java Collections-API ist die binäre Suche, die eine optimale Position des gesuchten Elements zurückgibt. Sollte das Element nicht gefunden werden, wird -1 zurückgegeben. Ein Beispiel für die Anwendung ist die Suche nach dem Namen "Eve" in einer Liste, die uns die Position 2 zurückgeben würde. Suchen wir jedoch nach "Benjamin", der nicht in der Liste enthalten ist, erhalten wir -1 als Ergebnis. Die Collections-API bietet außerdem noch viele weitere nützliche Funktionen, wie das Umdrehen von Reihenfolgen, die Suche nach Minimal- und Maximalwerten, das Kopieren von Datenstrukturen und das Erzeugen von nur lesbaren Kopien. Durch die Collections-API wurden auch Iteratoren eingeführt, die einen geordneten Zugriff auf Datenstrukturen ermöglichen sollen. Iteratoren sind ein Interface, das implementiert werden muss und bei den wichtigen Datenstrukturen der Collections-API bereits vorhanden ist. Mit der Methode "next()" wird das nächste Element in der Datenstruktur zurückgegeben und mit "hasNext()" kann abgefragt werden, ob weitere Elemente vorhanden sind. Seit Java Version 5 gibt es außerdem die foreach-Schleife, die direkt auf das Iteratoren-Konzept zugreift. Sie ist eine spezielle Variante der for-Schleife, die eine vereinfachte Schleifenverwaltung bietet. Im Schleifenkopf wird zuerst der Datentyp und die Variable deklariert, unter der die Werte im Schleifenkörper genutzt werden sollen, gefolgt von einem Doppelpunkt und der Referenzierung der Datenstruktur, über die iteriert werden soll. Die foreach-Schleife funktioniert auch mit Arrays. Wir möchten Ihnen nun anhand von Beispielen zeigen, wie foreach-Schleifen mit Arrays und Listen funktionieren. In unserem ersten Beispiel legen wir ein Array mit den Werten 2, 1 und 3 an, und nutzen dann eine foreach-Schleife, um nacheinander auf jeden Wert zuzugreifen. In unserem zweiten Beispiel erstellen wir eine Liste und fügen die Werte 2 und 1 hinzu. Auch hier nutzen wir eine foreach-Schleife, um auf die Werte zuzugreifen..
[Audio] Unsere Präsentation über Java setzt sich heute mit dem final Modifier in Java auseinander und wir befinden uns bereits bei Folie 12 von insgesamt 18. Der final Modifier verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können, was bedeutet, dass diese in der Unterklassen nicht mehr geändert werden können. Im weiteren Verlauf werden wir uns mit Konzepten und Ausblicken beschäftigen. Eine weitere Möglichkeit, Listen in Java zu durchlaufen, ist die foreach-Schleife, welche auch bei komplexen Datenstrukturen sehr hilfreich sein kann. Ein Beispiel dazu finden Sie auf Folie 25. Auch die Erstellung von grafischen Benutzeroberflächen ist eine wichtige Anwendung von Java, da es plattformunabhängig ist. Dafür wurde das Abstract Window Toolkit (AWT) eingeführt, welches die Erstellung von Fenstern und Dialogen ermöglicht, die unabhängig vom Betriebssystem immer gleich aussehen und funktionieren. Im Beispiel auf Folie 27 sehen Sie, wie man mit AWT ein Fenster mit einem Label und einem Button erstellen kann. Die fertigen Widgets machen es besonders einfach, eine benutzerfreundliche Oberfläche zu gestalten. Wir hoffen, dass Sie nun ein besseres Verständnis für die Möglichkeiten der grafischen Benutzeroberflächen in Java haben..
[Audio] Heute werde ich das Thema "Der finale Modifier in Java" näherbringen, speziell die Thread-Programmierung mit Java. Durch das Aufrufen von "new Fenster()" in der Main-Methode wird ein Fenster erzeugt und angezeigt. Allerdings fehlt noch die Möglichkeit, auf Eingaben zu reagieren und somit Interaktion mit der Benutzeroberfläche zu ermöglichen. Hierbei spielt das sogenannte Observer-Pattern eine wichtige Rolle. Dabei registrieren sich sogenannte Listener bei der Komponente und werden über Ereignisse, wie zum Beispiel Mausklicks, informiert. Diese Listener sind in Form von Interfaces vorhanden und können selbst implementiert werden. Um dem Beenden-Button aus unserem Beispiel eine Funktion zu geben, müssen wir einen eigenen Listener schreiben, der auf einen Klick auf den Button wartet. Dazu verwenden wir das ActionListener-Interface und implementieren die dazugehörige Methode "actionPerformed". Wir passen unsere Fenster-Klasse an, indem wir nicht nur den Beenden-Button erzeugen, sondern auch einen neuen Listener starten, der sich beim Button registriert. Dadurch wird bei einem Klick auf den Button das actionPerformed-Ereignis ausgelöst und der FensterSchliesser führt die darin definierte Methode aus, in unserem Fall "System.exit(0)". Ich hoffe, dass ich Ihnen einen Einblick in die Thread-Programmierung in Java geben konnte..
[Audio] Die finale Modifier in Java verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können. Auf der nächsten Folie werden wir uns mit weiterführenden Konzepten und einem Ausblick beschäftigen, der die direkte Unterstützung von neueren Prozessorarchitekturen für die parallele Ausführung mehrerer Operationen in einem Rechenzyklus betrifft. Dies macht Multi-Threading zu einem immer wichtiger werdenden Thema in Zukunft. Das Programmieren von Threads ist ein komplexes Thema, das zu den bereits bestehenden Fehlerquellen des Programmierens zusätzliche hinzufügt. Besonders kritisch wird es, wenn mehrere Threads Ressourcen teilen und zum Beispiel auf gemeinsame Variablen zugreifen müssen. In solchen Fällen ist besondere Vorsicht geboten. Zum Glück bietet Java von Haus aus einige Funktionalitäten zum Thema Multi-Threading an und ermöglicht somit eine nebenläufige Programmierung. Anhand eines Beispiels werden wir uns mit diesen vertraut machen und gleichzeitig auf mögliche Gefahren hinweisen. Angenommen, wir möchten eine Situation simulieren, in der zwei Personen gleichzeitig würfeln und eine dritte Person die Gesamtsumme der Augen zählt. Anstatt dies sequenziell zu lösen, soll dies tatsächlich gleichzeitig geschehen. Dafür legen wir eine Klasse an, die die Person repräsentiert, die die Ergebnisse aufsummiert. Diese Klasse enthält eine Variable namens "summe", die den aktuellen Stand der Gesamtsumme enthält, sowie eine Methode namens "übergebeErgebnis", die einen Wert hinzuaddiert. Diese Person ist jedoch kein Thread, da sie nur von den würfelnden Personen aufgerufen wird und somit erst bei Bedarf aktiv wird. Die würfelnden Personen hingegen sind Threads, die entweder von der Klasse "java.lang.Thread" erben oder das Interface "Runnable" implementieren müssen. In jedem Fall müssen sie die Methode "run" implementieren, die den auszuführenden Code enthält..
[Audio] Wir befinden uns jetzt auf Folie 15 von 18. Im folgenden Beispiel sehen Sie, wie wir den final Modifier in der Thread-Programmierung anwenden können. Auf Zeile 19 sehen Sie eine Methode, die eine zufällige Zahl an die Methode zaehler.uebergebeErgebnis übergibt. In der Run-Methode, die auf Zeile 22 beginnt, definieren wir den Programmcode, der als Thread ausgeführt werden soll. Wichtig zu beachten ist, dass die Threads nicht automatisch starten, wenn wir sie erstellen. Stattdessen müssen wir die start() Methode aufrufen, um die Threads zu starten und die run() Methode auszuführen. Jedoch kann es dabei zu einem typischen Fehler in der nebenläufigen Programmierung kommen. Um solche Fehler zu vermeiden, müssen wir die Methode synchronisieren, damit immer nur eine Person zur selben Zeit darauf zugreifen kann. Dies können wir mit dem synchronized Keyword tun, wie auf Zeile 9 und 10 ersichtlich. Das war Folie 15 von 18 und damit ist die Präsentation über die Thread-Programmierung mit Java beendet." "Im folgenden Beispiel sehen Sie, wie der final Modifier in der Thread-Programmierung mit Java angewendet wird. Auf Zeile 19 wird eine Methode gezeigt, die eine zufällige Zahl an die Methode "zaehler.uebergebeErgebnis" übergibt. In der Run-Methode, die auf Zeile 22 beginnt, wird der Programmcode definiert, der als Thread ausgeführt wird. Wichtig ist zu beachten, dass Threads nicht automatisch starten, wenn sie erstellt werden. Stattdessen muss die start() Methode aufgerufen werden, um die Threads zu starten und die run() Methode auszuführen. Jedoch kann es bei dieser Art der Programmierung zu typischen Fehlern kommen. Beispielsweise, wenn zwei Personen zur gleichen Zeit ihre Ergebnisse übermitteln, kann es zu einem Überschreibungsfehler kommen. Um solche Fehler zu vermeiden, muss die Methode synchronisiert werden, sodass immer nur eine Person zur selben Zeit darauf zugreifen kann. Dies wird mit dem synchronized Keyword, wie auf Zeile 9 und 10 zu sehen ist, gemacht. Damit haben wir Folie 15 von 18 abgeschlossen und hoffen, dass diese Präsentation Ihnen einen Einblick in die Verwendung des final Modifiers in der Thread-Programmierung gegeben hat..
[Audio] Unser letztes wichtiges Konzept, das wir besprechen möchten, ist der final Modifier. Dieser verhindert, dass Methoden und Attribute in Unterklassen überschrieben werden können. Somit kann die Funktionalität unserer Klasse nicht verändert werden. In unserem Beispiel der Klasse "ZaehlendePerson" haben wir den final Modifier beim Attribut "summe" verwendet. Dadurch bleibt der Wert unveränderlich und die Berechnungen bleiben korrekt. Ein weiteres Beispiel ist die synchronized Methode "uebergebeErgebnis", bei der der final Modifier sicherstellt, dass nur ein Thread gleichzeitig darauf zugreifen kann, um Konflikte und Fehler zu vermeiden. Dies war nur ein kurzer Einblick in die Welt der Thread-Programmierung mit Java. Es gibt viele weitere interessante Konzepte und Techniken, aber auch einige mögliche Probleme, die bei der nebenläufigen Programmierung auftreten können. Diese werden wir hier nicht weiter vertiefen. Wir hoffen, dass Sie durch diese Präsentation ein besseres Verständnis für die Konzepte der Java Programmierung gewonnen haben. Nun ist es an der Zeit, das Gelernte in der Praxis anzuwenden und noch weiter in die faszinierende Welt der Programmierung einzutauchen. Wir wünschen Ihnen viel Erfolg bei Ihren zukünftigen Projekten. Vielen Dank..
[Audio] Die heutige Präsentation behandelt die Vorteile von integrierten Entwicklungsumgebungen (IDEs). IDEs sind multifunktionale Werkzeuge, die verschiedene Funktionen wie Projekt-Manager, Debugger, Compiler und leistungsfähige Texteditoren vereinen. Sie bieten Programmierern hilfreiche Zusatzfunktionen wie Syntaxhervorhebung, Syntaxüberprüfung, Autovervollständigung und automatische Code-Formatierung. Durch die Möglichkeit, IDEs mit Plugins zu erweitern, können sie auch mehrere Programmiersprachen unterstützen. Besonders in Java-Projekten, wo jede Klasse in einer eigenen Datei gespeichert werden muss, behalten IDEs den Überblick und stellen sicher, dass Namenskonventionen eingehalten werden. Sie erleichtern die Organisation von Projekten mit vielen Dateien durch den Einsatz eines Projekt-Managers und stellen sicher, dass die in Java vorgeschriebenen Namenskonventionen eingehalten werden. Darüber hinaus bieten IDEs die Möglichkeit, durch nützliche Zusatztools die eigene Funktionalität zu erweitern, was zu einer individuellen Gestaltung der Entwicklungsumgebung und einer Optimierung des Programmierprozesses führt. Einige geeignete Texteditoren zum Programmieren sind Notepad++, SciTE, gedit und gvim. Diese sind alle als Freie Software verfügbar und für verschiedene Betriebssysteme geeignet. Wir hoffen, dass Ihnen diese Informationen einen Einblick in die Vorteile von IDEs gegeben haben. Wir sind nun auf Folie 18 angekommen, wo wir uns mit den möglichen Erweiterungen von IDEs beschäftigen werden..
[Audio] "Einfach nur noch toll! Liebe Zuhörerinnen und Zuhörer, herzlich willkommen zur letzten Folie unserer heutigen Präsentation. Wir haben bereits viel über die Verwendung von integrierten Entwicklungsumgebungen oder IDEs gesprochen, um effizienter und fehlerfreier zu programmieren. Heute möchten wir noch über eine weitere wichtige Funktion sprechen, die für Einsteiger in die Programmierung oft eine Hürde darstellt: den finalen Modifier in Java. Dieser Modifier verhindert, dass Methoden und Attribute von Unterklassen überschrieben werden können. Das kann nützlich sein, um beispielsweise veränderbare Klassen zu schützen oder sicherzustellen, dass eine bestimmte Methode immer auf eine bestimmte Art und Weise ausgeführt wird. Wir alle haben jedoch schon einmal das Problem gehabt, dass wir den falschen Namen für eine Variable gewählt haben oder dass unsere Bezeichnungen nicht aussagekräftig genug waren. In solchen Fällen ist es unabdingbar, dass wir unsere Klassen und Methoden umbenennen, um unsere Programmierung ordentlich und fehlerfrei zu gestalten. Das Problem dabei ist, dass es sehr mühsam sein kann, alle Dateien manuell zu durchsuchen, um sicherzustellen, dass die Umbenennung korrekt ist. Zum Glück bieten die meisten IDEs sogenannte Refactoring-Funktionen an, die uns diese Arbeit abnehmen und sicherstellen, dass wir keine Fehler in unserem Code übersehen. Eine weitere sehr nützliche Funktion, die bereits erwähnt wurde, ist der Debugger. Dieser hilft uns bei der Suche nach Fehlern und ermöglicht es uns, unser Programm Schritt für Schritt auszuführen und dabei zu überprüfen, ob alles wie geplant funktioniert. Wir können sogar zu jedem Zeitpunkt die Werte unserer Variablen überprüfen, um sicherzustellen, dass sie den erwarteten Wert haben. Das Herzstück einer guten IDE ist jedoch der Texteditor. Hier finden wir Standardfunktionen wie Syntaxhervorhebung, Syntaxprüfung, Code-Folding und Autovervollständigung. Die Syntaxhervorhebung hilft uns, einen schnellen Überblick über unseren Code zu bekommen, indem sie Schlüsselwörter und Befehle farblich hervorhebt. Die Syntaxprüfung ist vergleichbar mit einer Rechtschreib- und Grammatikprüfung und hilft uns dabei, Tippfehler und ungültige Satzkonstruktionen zu erkennen. Wir hoffen, dass wir Ihnen mit dieser Präsentation einen Einblick in die wichtigen Funktionen einer IDE geben konnten und Sie in Zukunft noch effizienter und fehlerfreier arbeiten können..