JAVA mit Netbeans Mag. Stefan Hagmann & Mag. Thomas Steiner BG und BRG Frauengasse Baden Diese Dokument wird unter folgenden creative commons veröffentlicht: http://creativecommons.org/licenses/by-nc-sa/3.0/at/ Inhaltsverzeichnis 1.Einleitung, Voraussetzungen......................................................................................................... 4 2.Editoren IDE's............................................................................................................................... 4 2.1.Eclipse................................................................................................................................... 4 2.2.Die Netbeans Oberfläche.......................................................................................................5 3.Grundlagen................................................................................................................................... 5 3.1.Das erste Programm.............................................................................................................. 5 3.2.Starten des Programm's über die Konsole.............................................................................6 3.3.Die Struktur der Dateien........................................................................................................ 7 3.4.Klassen und Packages.......................................................................................................... 7 3.5.Variablentypen....................................................................................................................... 7 3.6.Konvertierung von Zahlentypen.............................................................................................9 3.7.String zu Zahlentyp ............................................................................................................... 9 4.Strukturen - Fallbeispiele............................................................................................................... 9 4.1.Operatoren............................................................................................................................. 9 4.2.If - Abfragen......................................................................................................................... 11 4.3.Switch – Anweisung............................................................................................................. 12 4.4.Schleifenarten...................................................................................................................... 13 4.5.Methoden – functions........................................................................................................... 15 4.6.Arrays.................................................................................................................................. 16 4.7.Dynamische Listen – Container...........................................................................................17 4.8.Strings................................................................................................................................. 18 4.9.Klasse StringBuilder.............................................................................................................22 4.10.DATE/CALENDAR- Arbeit mit Datum und Zeit...................................................................23 4.11.Exceptions......................................................................................................................... 24 4.12.Erstellen und Einbinden von Packages..............................................................................26 4.13.Formatierung der Systemstandardausgabe.......................................................................27 4.14.Einlesen der Tastatur.........................................................................................................29 4.15.Dateien und Streams.........................................................................................................29 5.Rekursion.................................................................................................................................... 31 5.1.Bespiel: Fibonacci Zahlen....................................................................................................32 5.2.Beispiel Quicksort................................................................................................................32 6.OOP – Objektorientiertes Programmieren...................................................................................34 6.1.Zugriffsmodifizierer..............................................................................................................37 6.2.Getter und Setter................................................................................................................. 38 JAVA mit Netbeans Seite -1- 6.3.Konstruktoren...................................................................................................................... 38 6.4.Die static Methode ..............................................................................................................39 6.5.Mehrfachvererbungen - Interfaces.......................................................................................40 6.6.Verwendung der UML - Unified Modeling Language............................................................41 7.Fragen wir Dr. Java, Good to know.............................................................................................43 7.1.Bildschirmauflösung abfragen..............................................................................................43 7.2.Dynamisches Erstellen von Elementen................................................................................44 7.3.Warum erfolgt kein Repaint einer Komponente?..................................................................44 8.Threads mit Java......................................................................................................................... 44 8.1.Threads über das Interface Runnable..................................................................................44 8.2.wait() und notify()................................................................................................................. 45 8.3.Zugriff auf Daten aus einem Thread heraus.........................................................................46 8.4.Executors............................................................................................................................. 47 9.Grafische Anwendungen mit SWING...........................................................................................48 9.1.Mehrzeilige Labels............................................................................................................... 48 9.2.Actions und Events..............................................................................................................48 9.3.Mausereignisse erstellen.....................................................................................................49 9.4.Layout Manger..................................................................................................................... 50 9.5.Dialoge................................................................................................................................ 52 9.6.Die Sache mit den Pfaden, Icons, Images und Dateien.......................................................53 9.7.Die Sache mit dem JAR-File................................................................................................54 10.SWING Komponenten im Detail................................................................................................54 10.1.JTable Model...................................................................................................................... 54 10.2.Auf Ereignisse reagieren....................................................................................................55 10.3.Zellen darstellen un bearbeiten..........................................................................................55 10.4.Ein konkretes Beispiel .......................................................................................................56 10.5.Renderer und Editor in einer Klasse .................................................................................58 11.GDI............................................................................................................................................ 59 11.1.Zeichnen in einem Panel....................................................................................................59 11.2.Transformationen............................................................................................................... 59 11.3.Affine Transformation.........................................................................................................60 11.4.Punktierte Linie zeichnen...................................................................................................60 12.Erstellen von Java Applets für Webseiten..................................................................................60 12.1.Grundlagen........................................................................................................................ 61 12.2.Der HtmlConverter............................................................................................................. 61 12.3.Applets und jar-Dateien.....................................................................................................62 12.4.Erstellen und testen eines Applets.....................................................................................62 12.5.Testen des Projektes..........................................................................................................63 12.6.Automatischr Größenanpasseung des Applets an das Fenster.........................................64 13.Java Documentation erstellen...................................................................................................65 14.Virtual Machine steuern.............................................................................................................66 15.Netzwerkprogrammierung.........................................................................................................66 15.1.Datenpakete - TcpPackages..............................................................................................67 15.2.Paketarten......................................................................................................................... 67 16.SWING und Update von Komponenten.....................................................................................68 17.Zwischenablage und JAVA........................................................................................................ 69 Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -2- 1. Einleitung, Voraussetzungen Um Java programmieren zu können, braucht man einige Voraussetzungen am eigenen Computer 1. Java Runtime Umgebung 2. JDK, Java Development Kit 3. Netbeans als Editor Jede Software ist über http://developers.sun.com/downloads/index.jsp zu beziehen. Neben Netbeans kann man auch jeden anderen Editor verwenden. Erwähnt sei hier das Eclipse http://www.eclipse.org/ Projekt. Um ein Java-Programm auszuführen, benötigt man am Computer die JR (Java Runtime). Da es die JR für alle Betriebssysteme gibt, kann man Java-Programme auf jedem BS ausführen. 2. Editoren IDE's Im folgenden wird beschrieben, wie man die verschiedenen gängigen Editoren zum Arbeiten bringt. Netbeans arbeitet mit der SWING (SAF, swing application framework) Oberfläche, die momentan (2010) nicht mehr weiterentwickelt wird. Eine Alternative wäre BSAF, better swing application framework. Eclipse hingegen, arbeitet mit der SWT Oberfläche. 2.1. Eclipse Beachte: Das JDK muss bereist installiert sein. Herunterladen von: http://www.eclipse.org/ Eclipse muss nicht installiert werden, einfach aus dem Ordner heraus starten. Bevor man startet sollte man folgendes tun 1. Eclipse herunterladen und entpacken, die IDE for JAVA Developers reicht hier. 2. Deutsches Sprachpaket laden, vom Babel Projekt http://www.eclipse.org/babel/downloads.php (hier findet man alle Sprachen). Suche dir dort folgendes Paket BabelLanguagePack-eclipse-de_3... Auch entpacken, und in den Ordner von Eclipse kopieren. 3. Um mit SWT arbeiten zu können, noch SWT herunterladen von http://download.eclipse.org/eclipse/downloads/. Dort das letzte Release auswählen, und SWT Binaries herunterladen. 4. SWT (als zip File) Importieren mit Datei Importieren Allgemein Vorhandenes Projekt im Arbeitsbereich, dann das Zip File Auswählen und Fertigstellen. Wir erhalten im Projektbereich dieses Projekt, und können dmit arbeiten. 5. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -3- 2.2. Die Netbeans Oberfläche Beachte: Das JDK muss bereist installiert sein. Herunterladen von : http://netbeans.org/ Netbeans wird einfach installiert, und fertig. Netbeans zeigt alle Projekte in einem eigenen Fenster an. Hier kann man die Projekte einsehen und komfortabel verwalten. Links siehst ein Beispiel, wie das aussehen kann. Oft ist es hier verwirrend, wenn man ein bereits bestehendes Projekt importieren möchte. Es ist nicht der Befehl Open Project. Den verwendet man nur, wenn das Projekt mit dem Befehl Close geschlossen wurde (erkennbar am ). Wenn ein anderes Projekt aufgenommen werden soll, geht man wie Icon Kaffeehäferl folgt vor: • Neues Projekt • Java Project with existing Source • Dann die bestehenden Quellen des src Ordners angeben. Und dann wird das Projekt importiert. 3. Grundlagen 3.1. Das erste Programm Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -4- Der Haupteinstiegspunkt liegt in der Methode main. Dort lassen wir den üblichen ersten Text ausgeben „Hallo Java“. public class Main { public static void main(String[] args) { System.out.println("Hallo Java"); } } Mit dem Editor Netbeans drückt man nun die Taste F6 (Run Main Project) und sieht die Ausgabe im unteren Teil des Programms. 3.2. Starten des Programm's über die Konsole Manchmal möchte man ein Programm auch über die Konsole starten. Dazu muss man java.exe aufrufen, das gelingt aber nur, wenn man den Pfad kennt. Nehmen wir an, der Pfad zur java.exe liegt in C:\Program Files (x86)\Java\jre6\bin\. Man kann nun in Windows den Pfad permanent setzen (Systemsteuereung, u.s.w.), oder man erstellt sich ein Batch File, und setzt den Pfad bei Bedarf. Im Batch File steht folgendes @echo off echo JAVA Console echo Prepending 'C:\Program Files (x86)\Java\jre6\bin\' to PATH PATH=C:\Program Files (x86)\Java\jre6\bin\;%PATH% StartJavaConsole.bat Dann legt man sich eine Verknüpfung an, die folgendes startet Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -5- C:\Windows\System32\cmd.exe /k "StartJavaConsole.bat" Wie man erkennen kann, wird zur Laufzeit der Pfad zur java.exe gesetzt, und ab jetzt kann man sein Programm direkt starten. 3.3. Die Struktur der Dateien Welche Verzeichnisstruktur mit welchen Dateien erhalte ich nun? Schauen wir uns dazu die Verzeichnisstruktur genauer an. Das erste Programm erzeugt nebenstehende Verzeichnisstruktur. build: beinhaltet die *.class Dateien src: beinhaltet die *.java Dateien die anderen Ordner sind momentan nicht von Interesse für uns. Die *.java Dateien sind die Quellcode Dateien, während die *.class Dateien die bereits compilierten Dateien darstellen, die dann von der JR interpretiert werden. Wird das Projekt mit build ausgeführt (F11), erhält man eine *.jar Datei. Das ist im Prinzip eine zip-Datei in der alle *.class Dateien liegen. Starten kann man das Programm dann anschließend mit java -jar Console1.jar. Für Windows gibt es einige Tools um aus *.jar Files *.exe Dateien zu machen, z.B. JSmooth. Ein Package hingegen beinhaltet viele *.java Dateien, und dient als eine Art Bibliothek. Packages können beliebig oft von anderen Anwendungen verwendet werden. 3.4. Klassen und Packages Packages beinhalten Sammlungen von Klassen. Will man solche Klassen in seinem Programm verwenden, muss man diese mit dem import Befehl importieren. Zum Beispiel die String Klasse beinhaltet alles, was zum Arbeiten mit Strings nötig ist. Diese Klasse befindet sich im Package java.lang. Also importiert man diese Klasse mit import java.lang.String; Möchte man alles aus dem Package importieren, schreibt man einfach import java.lang.*; 3.5. Variablentypen Folgende Variablentypen haben wir in JAVA. Type Range byte -128 to +127 Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Andere Typen Type Seite -6- short -32,768 to 32,767 int -2,147,483,648 to 2,147,483,647 long -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 Approximate range -38 ... +3.4 × 10 Precision 38 float -3.4 × 10 7 digits double -1.7 × 10-308 ... +1.7 × 10308 15-16 digits char 0 to 65535 Unicode Zeichen bool true oder false Wie legt man nun Variable an, z.B. so Variablentyp Name; int x; /*Variable nicht initialisiert*/ int x = 2; /*initialisiert*/ String was = "Hallo Welt"; Char x = 'C'; float fltValue = 0.123456789; boolean myBool = true; Für die Bezeichnung von Variablen muss man sich an gewisse Regeln halten. Ein Bezeichner in Java kann beliebig lang sein und alle Stellen sind signifikant. Er muss mit einem UnicodeBuchstaben beginnen (d.h. 'A' bis 'Z', 'a' bis 'z', '_' und '$') und darf dann weitere Buchstaben und Ziffern enthalten. Es können auch Buchstaben aus anderen Landessprachen enthalten sein, allerdings darf es zu keinen Kollisionen mit reservierten Schlüsselwörtern kommen: abstract boolean break byte case catch char class const default do double else extends final finally float for if implements import instanceof int interface long native new private protected public return short static super switch synchronized throw throws transient try void volatile while Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -7- continue goto package this Die Literale true, false und null dürfen ebenfalls nicht als Bezeichner verwendet werden. 3.6. Konvertierung von Zahlentypen Ein Standardproblem ist es, einen Zahlentyp in einen anderen über zuführen. Man kann hier unterscheiden zwischen automatischer Konvertierung und expliziter Konvertierung. int x = 4711; double y; y=x; System.out.println(y); Automatische Konvertierung int > double int x,y; short z; x=10; y=20; z= (short)(x+y); System.out.println(z); Explizite Konvertierung int > short mit Hilfe des Type-Cast-Operators (siehe 4.1.2) 3.7. String zu Zahlentyp Wie funktioniert das? String zahl = "12.34"; double erg = Double.parseDouble(zahl) ; Double ist ein ein Objekt und beherrscht verschiedenste Methoden die zu diesem Zahlentyp passen. Beachte den unterschied zwischen double und Double! 4. Strukturen - Fallbeispiele 4.1. Operatoren Math. Operatoren Aktion += i += 10 entspricht i = i + 10 Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -8- -= i -= 10 entspricht i = i – 10 + Plus - Minus * Mal / Division % Modulo (berechnet Rest der Division) ++ i++ entspricht i=i+1 -- i-- entspricht i=i-1 Vergleichsoperatoren == Gleich != Ungleich > Größer < Kleiner >= Größer oder gleich <= Kleiner oder gleich Logische Operatoren && UND (beide Ausdrücke müssen wahr sein) || ODER incl (mind. 1 Ausdruck muss wahr sein) ^^ ODER excl (genau nur 1 Ausdruck darf wahr sein) bitweise Operatoren << bitweises verschieben nach links >> bitweise Operatoren Zuweisungsoperatoren = Einfache Zuweisung += Additionszuweisung -= Subtraktionszuweisung *= Multiplikationszuweisung a*=b äquivalent mit a= a*b /= Divisionszuweisung a/=b äquivalent mit a= a/b %= Modulozuweisung &= UND-Zuweisung a&=b weist a den Wert a & b zu Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans 4.1.1. Seite -9- |= ODER-Zuweisung ^= Exklusiv-ODER- Zuweisung <<= Linksschiebezuweisung ?:-Operator Der Fragezeichenoperator ist der einzige dreiwertige Operator in JAVA. Er erwartet einen logischen Ausdruck und zwei weitere Ausdrücke, die beide entweder numerisch, von einem Refereztyp oder vom Typ boolean sind. Bei der Auswertung wird zunächst der Wert des logischen Operators ermittelt. Ist dieser wahr, so wird der erste der beiden anderen Operatoren ausgewertet, sonst der zweite. Das Ergebnis des Ausdrucks a ? b : c ist also b, falls a wahr ist und c, wenn a falsch ist. Der Typ des Rückgabewerts entspricht dem Typ des größeren der beiden Ausdrücke b und c. 4.1.2. Type-Cast-Operator Mit disem Operator können explizite Typenumwandlungen (siehe 2.5.) vorgenommen werden. Er findet primär dann Anwendung, wenn der Compiler keine impliziten Konvertierungen unterstützt, z.B. bei der Zuweisung von größeren an kleiner numerische Typen oder der Umwandlung von Objekttypen. Der Ausdruck (type) a wandelt den Ausdruck a in einen Ausdruck vom Typ type um. Man sollte allerdings beachten, dass das Ergebnis von (type) a ein Ausdruck ist, der nur auf der rechten Seite des Zuweisungsoperators stehen darf, selbst wenn a z.B. eine Variable ist. 4.2. If - Abfragen Dient dazu Fälle zu unterscheiden. Üblicherweise gibt es nur 2 Möglichkeiten if (<Anweisung>){ … } else{ … } Wenn die Anweisung eintritt, wird der if Bereich ausgeführt. Tritt die Anweisung aber nicht ein, der else Bereich. Hier ein Beispiel if (zahl1<zahl2){ System.out.println("Die Zahl {0} ist größer als die Zahl {1}", zahl2, zahl1); } else{ System.out.println("Die Zahl {0} ist größer als die Zahl {1}", Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -10- zahl1, zahl2); } Wie können Anweisungen aussehen, in etwa so zahl1 == zahl2 zahl1 ist gleich zahl2? zahl1 != zahl2 zahl1 verschieden zahl2? zahl1 % zahl2 == 0 zahl1 modulo zahl2 gleich Null? (x ==1 ) && (y != 1) x gleich 1 UND y verschieden zu 1? Ausdruck1 || Ausdruck2 Boolscher Ausdruck1 oder Ausdruck2 Es ist auch möglich, eine Kurzschreibweise zu schreiben if (x<10){ y = 1; } else{ y = 0; } wird zu y = x<10 ?1:0; 4.3. Switch – Anweisung Die switch Anweisung ersetzt viele verschachtelte If Anweisungen. Die Syntax sieht wie folgt Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -11- aus switch (<Ausdruck>) { case <Konstante_1> //Anweisungen break; case <Konstante_2> //Anweisungen break; u.s.w } Als Beispiel wollen wir die Note eines Schülers abfragen int Note = …; switch (Note) { case 1: System.out.println("Sehr gut"); break; case 2: System.out.println("Gut"); break; case 3: case 4: case 5: System.out.println("Auch nicht schlecht!"); break; default: System.out.println("Nix gefunden"); break; } Wie hättest du diese Abfrage mit if-Anweisungen erstellt? Überlege! 4.4. Schleifenarten Schleifen sind ein wichtiges Instrument beim Programmieren. Sie haben die Aufgabe gewisse Befehle solange zu wiederholen, bis ein Ziel erreicht worden ist. Welchen Schleifentyp man verwendet ist an und für sich egal. 4.4.1. For-Schleife Die Syntax sieht wie folgt aus for (Variable; Bedingung; Weiterschalten) { //Anweisungen Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -12- } Solange die Bedingung erfüllt ist, zählt die Schleife in der Variable mit Weiterschalten weiter. for (int i=0; i<=101; i++) { System.out.println("Hallo das ist Satz Nr. "+ i); } Solange wie i kleiner oder gleich 101 ist, wird in Einserschritten i++ weiter gezählt und die Anweisungen ausgeführt. Mit dem break Befehl kann man auch vorzeitig eine Schleife verlassen. for (int i=0; i<=101; i++) { if (i==99) { break; /*Beenden der Schleife*/ } System.out.println("Hallo das ist Satz Nr. "+ i); } 4.4.2. verbesserte for-Schleife, foreach Diese Version erleichtert das Iterieren über alle Elemente in einem Array oder in anderen Arten von Collections. Da diese Anwendung eigentlich die häufigste darstellt, erweist sie sich als äußerst nützlich. for(String name:arrayName) { // tu irgendwas } Die Stringvariable name dient hier als Iterationsvariable, in der die einzelnen Werte aus dem Array für die weitere Verarbeitung im Anweisungsteil der Schleife aufgenommen werden. Die Elemente des Arrays müssen mit dem Variablentypen von Name übereinstimmen. Bei jeder Iteration wird ein neues Element aus dem Array aufgenommen. ArrayName steht für das Array oder die Collection, die durchforstet werden soll. 4.4.3. while - Schleife Die Syntax sieht wie folgt aus while (<Bedingung>) { //Anweisungen } Schauen wir uns dieses Beispiel an Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -13- int intVar = 0; while (intVar < 5) { intVar++; if (intVar == 3) break; System.out.println(intVar); } Wie man sehen kann, muss außerhalb der Schleife eine Zählvariable intVar definiert werden. Innerhalb der Schleife muss man diese Variable weiter zählen. Gerne vergisst man das, und erzeugt damit ungewollt eine Endlosschleife. 4.4.4. break Mit break kann man eine Schleife (for, while,do aber auch switch) vorzeitig verlassen. for(int i = 0; i < a.length; i++) { if (a[i] == 0) break; } Mit break ist es auch möglich, die Ausführung nach dem Abbruch hinter einem übergeordneten Programmblock fortzusetzen. Hierzu muss dem betreffenden Programmblock eine Marke vorangestellt werden, die dann bei der break-Anweisung angegeben wird. demo: { index = 0; while(index < a.length) { if (a[index++] == -1) break demo; } // Stelle 1 } // Stelle 2 4.5. Methoden – functions Wichtig ist die Unterscheidung ob Methoden mit oder ohne Rückgabewert erstellt werden. Eine explizite Unterscheidung ist hier nötig. /** * Eine öffentliche Methode ohne Rückgabewert */ public void Meinefunktion(){ } Wenn kein Rückgabewert existiert, schreibt man das Schlüsselwort void! Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -14- /** * Eine private Methode * @return die Zahl 12 */ private int Meinefunktion2(){ return 12; } Mit einem Rückgabewert muss der Typ des Wertes angeschrieben werden, hier int also Integer. 4.6. Arrays Werden wie in php folgendermaßen definiert, Typ[] Name. int[] chessboard; Point[][] points; Mit Inhalten befüllt wird ein Array so int[] prim = { 1, 2, 3, 5, 7, 7 + 4, }; String[] nouns = { "Haus", "Maus", "dog".toUpperCase(), /*DOG*/ new java.awt.Point().toString() }; Zugriffe geschehen über eine Indexnummer int[] zahlen = { 1, 2, 3, 5, 7, 7 + 4, }; System.out.println( zahlen.length ); System.out.println( zahlen[0]); System.out.println( zahlen[3]); Arrays mit bestimmter Länge erzeugen int[] zahlen = new int[100]; //erzeugt ein Array, das mit 100 Stellen, die jeweils mit dem Integer 0 initialisiert werden Auch mehrdimensionale Arrays sind Standard wie folgendes Beispiel zeigt zahlen[3][0] = 1; zahlen[1][3] = 4; Wobei es hierbei im Gegensatz zu vielen Programmiersprachen auch möglich ist, nichtrechteckige Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -15- Arrays zu erzeugen. Dies liegt daran, dass mehrdimensionale Arrays als verschachtelte Arrays gespeichert werden. /*Beispiel für ein dreieckiges Array*/ int[][]a ={{0}, {1,2}, {3,4,5}, {6,7,8,9}}; 4.7. Dynamische Listen – Container Da man oft nicht weiß wie viele Elemente gespeichert werden sollen, sind Arrays hier ein Problem. Bei dynamischen Listen können jeder Zeit Elemente gespeichert und gelöscht werden. Die Anzahl der Elemente muss nicht beachtet werden. Schauen wir uns ein Beispiel an import java.util.*; public static void main( String[] args ) { Collection c = new LinkedList<Integer>(); for ( int i = 0; i < 5; i++ ) c.add( "" + i ); System.out.println( c ); } Der Typ Collection erlaubt es beliebig viele Elemente zu speichern. Es stehen auch einige Methoden zur Verfügung: Methoden für ArrayLists add(Object elem) Fügt der Liste das Object elem hinzu remove(int index) Entfernt das Objekt mit dem angegebenen Index remove(Object elem) Entfernt dieses Objekt, falls vorhanden contains(Object elem) Liefert true falls vorhanden isEmpty() Liefert true, falls die Liste keine Elemente enthält indexOf(Object elem) Liefert den Index des Elements oder -1 size() Liefert die Anzahl der Elemente get(int index) Liefert das Object mit angegebenem Index Zu keiner Zeit braucht man sich Gedanke über die Anzahl der Element Gedanken machen. Die Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -16- Syntax Collection c = new LinkedList<Integer>(); oder LinkedList<Double> koord = new LinkedList<Double>(); gibt an, das ausschließlich Integer Typen in der Collection gespeichert werden. Als Containerklassen für Collections kommen die ArrayList und die LinkedList in Frage. Der Zugriff auf eine ArrayList ist schneller, während alle Elemente in der LinkedList untereinander verkettet sind, was das Behandeln der Reihenfolge einfacher macht. Weiters gibt es das HashSet, TreeSet, LinkedHashSet, HashMap, TreeMap, LinkedHashMap, WeakHashMap, LinkedList, ArrayBlockingQueue und PriorityQueue. Bitte hier in der Dokumentation nachlesen! 4.8. Strings Wie schon vorhin erwähnt benötigt man zum Arbeiten mit Strings die entsprechende Klasse aus dem java.lang-Package. Eine neue Stringvariable deklariert man nun folgendermaßen: String test = new String(); //eine leere Zeichenkette wird erzeugt; Man kann nun diese Variable auch gleich mit einer Zeichenkette initialisieren: String s = new String("Heute ist ein schöner Tag!"); 4.8.1. Initialisierung durch char-Arrays Zur Klasse String gibt es einen Konstruktor, der die Inhalte eines Arrays in eine Zeichenkette überträgt: char text[] = {'I','n','f','o','r','m','a','t','i','k'}; String s = new String(text); Durch die Angabe des Index und der Anzahl der Zeichen werden die Zeichen teilweise aus dem Array übernommen: char text[] = {'I','n','f','o','r','m','a','t','i','k'}; String s = new String(text,2,4); System.out.println(s); Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -17- Als Ausgabe erhalten wir erwartungsgemäß „form“. 4.8.2. Stringmethoden Die Klasse String liefert einige Methoden, die den Umgang mit Strings erleichtern. Um die Länge einer Zeichenkette zu ermitteln: String s = new String("Heute ist ein schöner Tag!"); System.out.println(s.length()); Um ein Zeichen an einer bestimmten Stelle auszugeben: System.out.print(s.charAt(5)); Weitere wichtige Methoden: Stringmethoden getChars() Auswahl einer zusammenhängenden Zeichenkette mit Startindex bis Endindex wird in eine Array geschrieben, beginnend mit dem Index start_ergebnis getChars(int start, int ende, char ergebnis[], int start_ergebnis) 4.8.3. indexOf() Liefert die Position des ersten Auftretens des angegebenen Zeichens (bzw. Zeichenkette) substring() Liefert eine Teilzeichenkette mit Startindex und Endindex replace() Ersetzt in einer Zeichenkette ein bestimmtes Zeichen durch ein anderes replace( char alt, char neu) trim() Entfernt vorangehende und anschließende nicht druckbare Zeichen Operatoren für Zeichenketten Man kann mehrere Zeichenketten mit Hilfe von concat() verketten: String s1 = new String("BRG"); String s2 = new String("Frauengasse"); System.out.println(s1.concat(s2).concat("!")); Um Zeichenketten und Variablenwerte nebeneinander zu verwenden, verkettet man diese mit „+“: int a = 10; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -18- int b = 20; System.out.println(a + " + " + b + " = " + a + b); System.out.println(a + " + " + b + " = " + (a + b)); Man beachte die unterschiedlichen Ausgaben. Um vor der Verkettung Berechnungen auszuführen (wie hier z.B. a+b ), muss man Klammern verwenden, da sonst das „+“ als Verkettungsoperator interpretiert wird. Man kann 2 Zeichenketten mit Hilfe der Methode equals() auf Gleichheit überprüfen. Die Ausgabe liefert Boolesche Werte. String s = new String("hallo"); System.out.println(s.equals("hallo")); Sonstige Vergleichsmethoden equalsIgnoreCase() Beim Vergleichen wird Groß/Kleinschreibung igoriert startsWith() Überprüft ob ein String mit einer bestimmten Zeichenkette beginnt endsWith() Überprüft ob ein String mit einer bestimmten Zeichenkette endet (Ergebnis:Boolescher Wert) compareTo() Überprüft neben der Gleichheit der Zeichenketten die alphabetische Abhängigkeiten (vgl. Wörterbuch). Das Ergebnis ist eine ganze Zahl: Steht die aufrufende Zeichenfolge im Wörterbuch vor der angegebenen, so liefert compareTo() eine negative Zahl; bei Gleichheit Null. Steht die aufrufende Zeichenkette im Wörterbuch nach der angegebenen, so ist das Ergebnis eine positive Zahl. regionMatches() Vergleicht zwei gleich lange String-Regionen, die in zwei unterschiedlichen Strings an zwei unterschiedlichen Positionen liegen können auf Gleichheit Syntax: regionMatches(int <Position 1. Zeichenkette>, String<2. Zeichenkette>, int <Position 2. Zeichenkette>, int <Länge der Region>) Wenn die Groß- und Kleinschreibung ignoriert werden soll, wird als zusätzlicher Parameter an erster Stelle ignoreCase hinzugefügt. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -19- Kleines Beispiel zu compareTo() : String s = new String("hallo"); System.out.println("hallo: " + s.compareTo("hallo")); System.out.println("ha: " + s.compareTo("ha")); System.out.println("Hallo: " + s.compareTo("Hallo")); System.out.println("abc: " + s.compareTo("abc")); System.out.println("hallo - ist da jemand: " + s.compareTo("hallo ist da jemand")); System.out.println("huch: " + s.compareTo("huch")); liefert folgende Ausgabe: hallo: 0 ha: 3 Hallo: 32 abc: 7 hallo - ist da jemand: -16 huch: -20 Kleines Beispiel zu regionMatches(): System.out.println(„Grüße aus Baden“.regionMatches(8,“Greetings from Austria“,8,2); //Vergleicht, ob eine Region der Länge 2 jeweils an der Position 8 der beiden Strings ident ist und liefert in diesem Falle „true“ 4.8.4. Anwendungsbeispiel „BUBBLESORT“ String satz[] = {"informatik", "ist", "schön", "und", "lehrer", "lügen", "nicht"}; for (int i = 0; i < satz.length; i++) { for (int j = i+1; j < satz.length; j++) { if (satz[j].compareTo(satz[i]) < 0) { String wort = satz[i]; satz[i] = satz[j]; satz[j] = wort; } } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -20- System.out.println(satz[i]); } 4.9. Klasse StringBuilder Ebenso wie bei Arrays kann man an Strings grundsätzlich keine zusätzlichen Zeichen anhängen oder auch nur die zumindest die Länge verändern. Zu diesem Zwecke hat man zwei Klassen implementiert: StringBuffer und StringBuilder. Da StringBuilder als neuere die ressourcenschonendere und schneller Klasse darstellt, werden wir uns vorerst einmal auf diese Klasse beschränken, wobei ja beide Klassen soundso dieselben Methoden besitzen. Ein leerer StringBuilder wird erzeugt mit StringBuilder(). Wird ein String übergeben, so wird ein StringBuilder-Objekt erzeugt, das eine Kopie der übergebenen Zeichenkette enthält (StringBuilder(String a) ). 4.9.1. Methoden Methoden der StingBuilder-Klasse append(String s) String s wird am Ende des Objektes angehängt insert (int offset, Sting s) An der Position offset wird String s in das Objekt eingefügt deleteCharAt(int index) Einzelnes Zeichen wird an der Position index gelöscht wird delete(int start, int end) Entfernt einen Teilstring setCharAt(int index, Ersetzt ein Zeichen an angegebener Position char c) replace(int start, int end, String str) 4.9.2. length() Länge capacity() Wert des belegten Pufferspeichers Konvertierung in einen String Wenn man mit der Manipulation der Zeichenkette fertig ist, kann man ein StringBuilder-Objekt wieder in einen String verwandeln. Mit der Methode String toString() kann man dies effizient machen, wobei erst bei erneuter Veränderung des StringBuilder-Objektes eine Kopie der Zeichenkette erstellt wird. Ansonsten wird nur ein Zeiger auf den Zeichenspeicher gelegt, was Ressourcen spart. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -21- 4.10. DATE/CALENDAR- Arbeit mit Datum und Zeit Wenn man einen Zeitstempel benötigt, verwendet man die date-Klasse (java.util.Date). Es dient eigentlich zum Speichern eines Datum-/Zeitwertes (als 64-Bit-Long-Variable) in ms (Millisekunden) seit 1970-01-01 0h UTC (negative Werte sind vor 1970). // Aktuelles Datum: import java.util.*; Date dt = new Date(); System.out.println( "Date = " + dt ); // z.B. 'Fri Jan 26 19:03:56 GMT+01:00 2001' System.out.println( "ms = " + dt.getTime() ); // z.B. '980532236731' Das Calendar-Objekt verwendet man für Berechnungen mit Datums- und Zeitwerten. // Verschiedene Verfahren zur Erzeugung eines Kalender-Objekts: import java.util.*; Calendar myCal1 = Calendar.getInstance(); // lokales Kalendersystem mit aktueller Zeit Calendar myCal2 = new GregorianCalendar(); // GregorianCalendar mit aktueller Zeit Calendar myCal3 = new GregorianCalendar(1956,Calendar.MARCH,17); // GregorianCalendar mit vorgegebener Zeit // Setzen von Jahr + Monat + Tag: myCal2.set( 1956, Calendar.MARCH, 17 ); // ändert so nicht Stunden, Minuten und Sekunden myCal2.setTime( myCal2.getTime() ); // nicht mehr unbedingt notwendig seit JDK 1.2 // Zeit setzen mit Date: myCal2.setTime( new Date() ); // Einzelne Felder extrahieren: int year = myCal2.get( Calendar.YEAR ); Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -22- int mnth = myCal2.get( Calendar.MONTH ) + 1; // nicht vergessen die 1 zu addieren int date = myCal2.get( Calendar.DATE ); System.out.println( date + "." + mnth + "." + year ); Formatierung ist SimpleDateFormat besser // für SimpleDateFormat format = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); datum = format.parse(dstr); // Calendar ist gut geeignet, um Berechnungen durchzuführen, // z.B. um den um ein Jahr erhöhten Zeitwert zu berechnen: myCal2.add( Calendar.YEAR, 1 ); // Umwandlung von Calendar in Date: Date myDate = myCal2.getTime(); System.out.println( myDate ); Methoden der Calendar-Klasse set Um die Zeit auf einen bestimmten Wert zu setzen Beispiel: cal.set(2009,3,29,10,00) add Um zB. 35 Tage zum Datum zu addieren cal.add(c.DATE,35) roll Datum um 35 Tage „rollieren“(vordrehen), Monat belibt unverändert SetTimeInMillis, getTimeInMillis das Datum in Millisekunden umwandeln get Auslesen von Teilinformationen (YEAR, MONTH, DAY_OF_MONTH, DAY_OF_WEEK , HOUR_OF_DAY , MINUTE , SECOND 4.11. Exceptions Exceptions sind Fehler, Ausnahmen die in einem Programm passieren. Üblicherweise stürzt das Programm dann ab. Ein gutes Programm tut das allerdings nicht, nur muss der Programmierer diese Fehler auffangen und behandeln. Als Beispiel nehmen wir dieses Programm double erg; erg = 100/0; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -23- Das Programm muss abstürzen, da eine Division durch 0 nicht gestattet ist. Exeptions werden immer dann ausgelöst, wenn im Programmfluss ein Fehler auftritt. Im Regelfall stürzt das Programm mit einer Fehlermeldung ab (bekannt von Windows). Der fleißige Programmierer kann aber solche Fehler abfangen und darauf reagieren, und somit das Programm vor Abstürzen schützen. Klingt kompliziert? Ist es nicht. Schauen wir uns den folgenden Programmcode an int zahl=0; boolean err = false; try { zahl = (int) zahl; } catch (ArithmeticException ex) { System.out.println("Bitte IRGENWAS eingeben!" + ex.getMessage()); err = true; } catch(Exception ex2){ System.out.println("Allgemeiner Fehler" + ex.getMessage()); err = true; } finally { System.out.println("finally wird IMMER ausgeführt"); if (!err) System.out.println(zahl); } Für jeden Fall eines Fehlers gibt es im Allgemeinen einen eigenen Exceptiontyp. Welchen Typ man abfragen kann, findet man in der Hilfe des Programms. Üblicherweise fängt man Fehler in einem try catch Block ab. Passiert im try Block ein Fehler, geht das Programm zum entsprechenden catch Block über, und arbeitet dort weiter. Man kann hier beliebig viele catch Blöcke definieren. Das Programm stürzt nun nicht mehr ab, und arbeitet weiter. Der finally Block wird auf jeden Fall ausgeführt. 4.11.1. throws im Methodenkopf angeben Neben dem üblich try-catch Statements, kann man auch im Kopf der betreffenden Methode eine throws-Klausel einführen. Dadurch stürzt die Methode nicht mehr ab, sondern gibt den Fehler an die aufrufende Instanz weiter. Die aufrufenden Instanzen können dann auf den Fehler reagieren. static double Division(double zahl) throws ArithmeticException, Exception{ return zahl/0; } try{ Division(100.1); } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -24- catch(ArithmeticException ex){ System.out.println(ex.getMessage()); } catch(Exception ex){ System.out.println(ex.getMessage()); ex.printStackTrace(); } Im obigen Beispiel sieht man, das die Methode nicht auf etwaige Exceptions reagiert, sondern diese mit dem throw Befehl weitergibt. Der throw Befehl ermöglicht es, manuell Exceptions auszulösen, z.B. so: throw new ProtocolException(); 4.12. Erstellen und Einbinden von Packages Oft programmiert man Routinen, die man wiederverwenden möchte. Stell dir Methoden vor, die auf Knopfdruck z.B. die Fläche von Rechtecken, Parallelogrammen oder Trapezen berechnet. Warum soll man diese Methoden jedes mal neu programmieren wenn man sie benötigt. Hier kommt das Package ins Spiel. Ein Package ist eine Sammlung von Routinen, die man jederzeit wiederverwenden kann. Das Erstellen ist ganz einfach. Wichtig zu wissen ist, das jedes Package ein eigenes Unterverzeichnis haben muss. Durch einen einfachen Rechtsklick auf SourcePackages kann man neue Packages erstellen (hier MathPackage). Ein Package kann viele *.java Quelldateien beinhalten. Die *.java Datei beinhaltet als erste Zeile package MathPackage; sonst programmiert man wie gewohnt. Wenn man nun das Package verwenden möchte, muss man das Package mit dem import Befehl eingliedern (vergleich dazu auch 3.4. Klassen und Packages). Ab dann kann man auf alle Methoden und Variable zugreifen (beachte die Zugriffsmodifizierer wie public, private). package testpackages; import MathPackage.Vierecke; public class Main { public static void main(String[] args) { Vierecke veck = new Vierecke(); System.out.println("Verwendung eines externen Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -25- Packages ..."); double fl = veck.Flaeche_Rechteck(12, 14); System.out.println("Fläche eines Rechteckes: " + fl); } } Im Umgang mit Paketen sollte man ein paar Regeln beachten: 1. Was zu einem Paket gehört ist außerhalb unsichtbar Diese Regel hat den Zweck, dass man in verschiedenen Paketen dieselben Namen verwenden kann. Man muß bei selbst entwickelten Paketen nur darauf achten, dass es zu keinen Namenskollisionen innerhalb des Paketes kommt. Man sollte sicherstellen, dass die eigenen Klassen nur von berechtigten Methoden und Klassen gesehen und manipuliert werden können. 2. Namen können von einem Paket exportiert werden Mit dem Zusatz public können Klassen, Methoden, Felder und Konstruktoren exportiert werden, nicht jedoch Parameter oder lokale Variablen. Eine exportierte Methode ist in anderen Paketen nur dann sichtbar, wenn auch die zugehörige Klasse exportiert wurde. 3. Exportierte Klassen können in anderen Paketen importiert werden 4.13. Formatierung der Systemstandardausgabe Nachdem man über System.out.println zwar schnell und komfortabel eine Ausgabe erzeugen kann, findet man aber keine Möglichkeiten, diese Ausgabe ordentlich zu formatieren. In den Klassen String und PrintStream gibt es dafür die Methode format(). for(int i=5; i < 199; i += 45) { System.out.format(„Aktueller Wert: %3d%n“, i); } Die Angabe %3d%n erzwingt eine Ausgabe einer 3-stelligen Ganzzahl und anschließendem Zeilenvorschub. Optionen b Boolescher Wert c Einzelnes Zeichen d, o, x Ganzzahl in Dezimal-, Oktal- bzw. Hexadezimaldarstellung X Darstellung in Hexadezimaldarstellung nur mit großen Buchstaben f Gleitkommazahl Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -26- e, E Gleitkommazahl mit Exponent bzw. mit großem „E“ g, G Gleitkommazahl in gemischter Schreibweise bzw. mit großem „E“ t Präfix für Datums-/Zeitangaben, wobei anschließend angegeben werden muss, welcher Teil des Date- bzw. CalendarObjektes angegeben wird (H,M,S,d,m,Y,F,c) s Strings und andere Objekte Man sollte allerdings genau auf Typenkonformität achten! Einige weitere Beispiele: //Boolesche Werte System.out.format("%b %b %2$b %1$b%n", true, false); //Ganzzahlen System.out.format("[%d]%n", -2517); System.out.format("[%7d]%n", -2517); System.out.format("[%-7d]%n", -2517); System.out.format("[%(7d]%n", -2517); System.out.format("[%07d]%n", -2517); System.out.format("[%,7d]%n", -2517); System.out.format("%1$d %<o %<x %<X%n", 127); //Fliesskommazahlen System.out.format("%f%n", 0.000314); System.out.format("%1$6.2f %1$6.2e %1$6.2E %1$6.2G%n", 3.141592); System.out.format("%,8.2f%n", 31415.92); System.out.format(Locale.ENGLISH, "%,8.2f%n", 31415.92); //Zeichen und Strings System.out.format("%c%c%c\n", 97, 64, 98); System.out.format("%s nein\n", "ja"); Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -27- //Datum/Uhrzeit Calendar now = Calendar.getInstance(); System.out.format( "%1$td.%1$tm.%1$tY %1$tH:%1$tM:%1$tS%n", now ); System.out.format("%tF%n", now); System.out.format("%tc%n", now); 4.14. Einlesen der Tastatur Mit der passenden Klasse ist alles ganz einfach. Scanner s = new Scanner(System.in); int x = s.nextInt(); String msg = s.next(); oder so geht es auch ... import java.io.*; private String ReadLine(){ BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String s =""; try { s = in.readLine(); } catch(IOException ex){ return ""; } return s; } Der BufferedReader übernimmt für uns die Aufgabe das Ende der Eingabe zu suchen. Arbeitet man mit System.in.Read() erhält man bloß ein Char[] und muss sich selbst um das Auslesen der gesamten Eingabe kümmern. 4.15. Dateien und Streams Es gibt Klassen mit denen man Dateien lesen und beschreiben kann. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -28- File f = new File( dateiname ); byte[] buffer = new byte[ (int) f.length() ]; InputStream in = new FileInputStream( f ); in.read( buffer ); in.close(); In diesem Beispiel wird die gesamte Datei in einen InputStream gelesen, das kann bei großen Dateien sehr lange dauern, und ist daher nicht zu empfehlen. Für Textdateien steht eine spezielle Klasse FileWriter und FileReader zur Verfügung. Dazu muss aber das entsprechende Package eingebunden werden. class java.io.FileWriter Writer fw = null; try { fw = new FileWriter( "TextDatei.txt" ); fw.write( "Das ist eine Zeile!" ); //Zeilenvorschub fw.append( System.getProperty("line.separator") ); } catch ( IOException e ) { System.err.println( "Konnte Datei nicht erstellen" ); } fw.close(); Für das Lesen von Dateien würde man folgende Struktur verwenden public void ReadFile(String filename){ try{ BufferedReader rd = new BufferedReader(new FileReader(filename)); //bis zum Ende der Datei lesen String buffer =""; while((buffer = rd.readLine()) != null){ //Ausgabe auf die Konsole System.out.println(buffer); } } catch(FileNotFoundException ex){ } catch(IOException ex){ } } Der entscheidende Teil ist der BufferedReader, der die Aufgabe hat, den Datenstrom aus der Datei in Strings umzuwandeln. Beachte auch diese Zeile while((buffer = rd.readLine()) != null). Das ist eine sehr kurze Schreibweise für die Laufbedingung der While-Schleife. Das bedeutet, das so lange eine Zeile gelesen wird, bis der Datenstrom aus ist, also null. Für das Schreiben in eine Datei verwendet man den BufferedWriter,siehe anschl. Beispiel. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -29- Beispiel: Lesen von der Tastatur und Schreiben in eine Datei Um eine Eingabe von der Tastatur zu verarbeiten, gibt es (vgl. zur Standardausgabe) auch die Standardeingabe mit System.in. Der Eingabe-Stream System.in ist ein Exemplar der Klasse InputStream und besitzt somit auch deren Methoden. Die Eingabe wird in diesem Fall mit der Methode read() vorgenommen. Hierdurch wird das Array buffer mit den vom Benutzer auf der Standardeingabe eingegebenen Zeichen Byte-weise gefüllt: read = System.in.read(buffer, 0, 80); Im folgenden Beispiel wird nun die Tastatureingabe in die Datei daten.txt gespeichert. public static void main(String args[]) { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Tastatureingabe: "); try { String s = in.readLine(); System.out.println("Kontrollausgabe: "+s); try{ BufferedWriter out =new BufferedWriter( new OutputStreamWriter(new FileOutputStream("daten.txt"))); out.write(s); out.newLine(); out.close(); System.out.println("Ihre Daten wurden in daten.txt gespeichert"); } catch(FileNotFoundException e){ System.out.println(e.getMessage());}} catch(IOException e){System.out.println(e.getMessage());}} 5. Rekursion Methoden können in JAVA nicht nur andere Methoden sondern auch sich selbst aufrufen, was man als rekursiven Aufruf bezeichnet. Diese Technik gehört zum Grundwerkzeug jedes erfahrenen Programmierers, da es meist weit elegantere Lösungen bietet als iterative Lösungsmöglichkeiten. Am besten sieht man den Nutzen der Rekursion anhand eines Beispieles: Wir wollen die Fakultät einer natürlichen Zahl berechnen. n !=1⋅2⋅3⋅⋅n−1⋅n Das wäre eine iterative Definition. Rekursiv versucht man nun das „Problem“ auf sich selbst zurück zu führen. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -30- Wir erkennen, dass die ersten n-1 Faktoren des Produkts die Zahl (n – 1)! ergeben, was uns zu einer rekursiven Definition führt: n! = (n – 1) ! * n n! = 1 für für n>1 n=1 Somit wird das Problem auf ein etwas kleineres gleichartiges Problem zurückgeführt, was man solange macht, bis die Berechnung abgeschlossen ist. Die Implementierung könnte nun so aussehen: long fact(int n) {if(n==1) {return 1;} else { return fact(n-1)*n;}} Man könnte vereinfacht sagen: Wenn (Problem klein genug) führe nichtrekursiven Zweig ausführung sonst führe rekursiven Zweig aus 5.1. Bespiel: Fibonacci Zahlen Die Fibonaccifolge stellt ein sehr einfaches Beispiel für die rekursive Programmierung dar. Allerdings muss man leider auch beachten, dass die rekursive Lösung in diesem Fall die ressourcenintensivste darstellt, da die Funktion mehrfach mit denselben Parametern aufgerufen wird, was wiedeum viel Speicher benötigt. Trotzdem kann man anhand dieses Beispieles Rekursionen sehr leicht analysieren und verstehen. public static long fib(int a){ if (a==1||a==2) return 1; else return fib(a-1)+fib(a-2); } Für die Parameter 1 und 2 wird jeweils 1 zurückgegeben, bei allen anderen Zahlen wird die Funktion mit den Parametern a-1 und a-2 aufgerufen. 5.2. Beispiel Quicksort Ein wichtige Anwendung der Rekursion stellen Sortier- und Suchalgorithmen dar. Man nimmt eine Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -31- Liste von Elementen und teilt diese in zwei Hälften. Zunächst wird die zu sortierende Liste in zwei Teillisten („linke“ und „rechte“ Teilliste) getrennt. Dazu wählt Quicksort ein sogenanntes Pivotelement aus der Liste aus. Alle Elemente, die kleiner als das Pivotelement sind, kommen in die linke Teilliste, und alle, die größer sind, in die rechte Teilliste. Die Elemente, die gleich dem Pivotelement sind, können sich beliebig auf die Teillisten verteilen. Nach der Aufteilung sind die Elemente der linken Liste kleiner oder gleich den Elementen der rechten Liste. Anschließend muss man also nur noch jede Teilliste in sich sortieren, um die Sortierung zu vollenden. Dazu wird der Quicksort-Algorithmus jeweils auf der linken und auf der rechten Teilliste ausgeführt. Jede Teilliste wird dann wieder in zwei Teillisten aufgeteilt und auf diese jeweils wieder der Quicksort-Algorithmus angewandt, und so fort. Diese Selbstaufrufe werden als Rekursion bezeichnet. Wenn eine Teilliste der Länge eins oder null auftritt, so ist diese bereits sortiert und es erfolgt der Abbruch der Rekursion, d.h. für diese Teilliste wird Quicksort nicht mehr aufgerufen. Die Längen der Teillisten ergeben sich aus der Wahl des Pivotelements. Idealerweise wählt man das Pivot so, dass sich zwei etwa gleich lange Listen ergeben, dann arbeitet Quicksort am effizientesten. Es sollte also etwa gleich viele Elemente kleiner als das Pivot und größer als das Pivot geben. daten[0], daten[1],... , daten[n-1]. funktion quicksort(links, rechts) falls links < rechts dann teiler := teile(links, rechts) quicksort(links, teiler-1) quicksort(teiler+1, rechts) ende ende Die folgende Implementierung der Funktion teile teilt das Feld so, dass sich das Pivotelement an seiner endgültigen Position befindet und alle kleineren Elemente davor stehen, während alle größeren danach kommen: funktion teile(links, rechts) i := links // Starte mit j links vom Pivotelement j := rechts – 1 pivot := daten[rechts] wiederhole // Suche von links ein Element, welches größer als das Pivotelement ist wiederhole solange daten[i] ≤ pivot und i < rechts i := i + 1 ende // Suche von rechts ein Element, welches kleiner als Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -32- das Pivotelement ist wiederhole solange daten[j] ≥ pivot und j > links j := j - 1 ende falls i < j dann tausche daten[i] mit daten[j] solange i < j // solange i an j nicht vorbeigelaufen ist // Tausche Pivotelement (daten[rechts]) mit neuer endgültiger Position (daten[i]) falls daten[i] > pivot tausche daten[i] mit daten[rechts] ende // gib die Position des Pivotelements zurück antworte i ende 6. OOP – Objektorientiertes Programmieren Alle modernen Programmiersprachen setzen auf Objekte beim Programmieren. Die Programmierung wird dadurch viel einfacher in der Handhabung. Anstatt eines linearen Codes hat man Objekte zur Verfügung, die gewisse Aufgaben erledigen können. Diese Objekte erstellt man, wenn man sie benötigt und teilt ihnen Aufgaben zu. Im Allgemeinen ist OOP flexibler, leistungsfähiger und bei größeren Programmen einfach übersichtlicher. Die Übersichtlichkeit kann man mit diversen Zugriffsmodifizierer (vergl. 6.1. Zugriffsmodifizierer auf Seite 36) steuern. Sehen wir uns ein Beispiel aus der Mathematik an Shape Alle angeführten Objekte sind abgeleitet von der Basisklasse Shape. ● Die Eigenschaften der Basisklasse werden an die nachfolgenden Objekte vererbt ● Jedes Objekt hat Eigenschaften und Methoden ● Methoden der Basisklasse könne überschrieben werden ● Rechteck Ellipse Quadrat Kreis Warum leitet sich z.B. ein Quadrat von einem Rechteck ab? Die Antwort kennst du aus der Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -33- Mathematik. Jedes Quadrat ist auch ein Rechteck, das Quadrat ist nur eine spezielle Form des Rechtecks. Wenn also die Fläche eines Rechtecks mit Seite x Seite zu berechnen ist, dann ist es auch beim Quadrat so. Shape ist das allgemeinste Objekt. Es hat allgemeine Eigenschaften eines Körpers in 2D, also eine Begrenzungslinie, eine Fläche und einen Umfang etc. Die Definition könnte so aussehen Shape Objektnamen Linie: 2px Linenfarbe:rot Dichte: 3.4 Eigenschaften Zeichnen() Flaeche(); Umfang();Volumen(); Masse() Methoden Von dieser Klasse leiten wir nun das Rechteck ab, das ist eine Spezialisierung des Shapes. Rechteck Linie, Linenfarbe Laenge Breite Länge und Breite sind eine spezielle Eigenschaft von eine Rechteck, während Linie, Linienfarbe bereits von Shape geerbt worden sind, Zeichnen() Flaeche() Umfang() Diagonale() Die Methode Diagonale() ist wieder eine spezielle Eigenschaft, der Rest wurde geerbt. Der dazu passende Quellcode sieht so aus: public class Shape2D { protected int Linie; protected int Linienfarbe; protected double dichte = 1.0; public Shape2D () { } public abstract void Zeichnen (); public abstract double Volumen (); public double Masse (){ return Volumen * dichte; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -34- /* Hier wird bereits mit dem Volumen gerechnet, obwohl es abstrakt ist! */ } public void Flaeche () { } public void Umfang () { } } Die Methode Zeichnen() ist abstrakt, es muss nur der Kopf definiert werden. Man kann zwar jedes Objekt der Klasse Shape zeichnen, allerdings muss dies für jedes Objekt extra implementiert werden. Man nennt Klassen, die zumindest eine abstrakte Methode enthalten, abstrakte Klassen. Man sollte allerdings beachten, dass man keine Objekte dieser Klasse erzeugen kann, sehr wohl aber von den Unterklassen. Ein kleines Beispiel soll das verdeutlichen: abstract class Animal{ boolean likes(String food){return false;} abstract void speak(); void getAngry(){speak();} Wir haben also eine abstrakte Tierklasse, in der zwar jedes Tier speaken kann, allerdings spricht jedes Tier anders. Wenn wir jetzt ein neues Objekt erzeugen wollen, müssen wir vorsichtig agieren: Animal a1 = new Animal(); //ist nicht erlaubt Animal a2 = new Bird(); //ist erlaubt a2.speak(); // liefert „beep“ Wieder zurück zur Geometrie: Die Methode Flaeche() hingegen ist nicht abstrakt, und muss bereits hier aus programmiert werden. Das abgeleitete Rechteck sieht nun so aus: public class Rechteck extends Shape2D { public int Laenge; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -35- public int Breite; public Rechteck () { } public void Diagonal () { } public void Zeichnen () { } @Override public void Umfang () { } @Override public void Flaeche () { } } Eine Klasse wird von einer anderen Klasse abgeleitet mit der Schreibweise Neue Klasse extends Mutterklasse. Die Methode Flaeche() muss mit @Override neu definiert werden. Ansonsten weiß man nicht ob die Methode Flaeche() von der Klasse Shape oder von der Klasse Rechteck kommt! Rechteck definiert neu Laenge und Breite, hat aber zusätzlich noch die Eigenschaften Linie und Linienfarbe der Klasse Shape (vererbt). Überlege selbst, wir die Klasse Quadrat aussehen muss! 6.1. Zugriffsmodifizierer Zugriffsmodifizierer steuern die Sichtbarkeit von Elementen eines Objektes. Die wichtigsten für uns sind • public • private • protected Eigenschaften oder Methoden die mit public gekennzeichnet sind, dürfen von außerhalb des Objektes angesprochen werden. Mit private gekennzeichnete Element sind NUR innerhalb des Objektes verwendbar. Wenn man eine Spezialisierung einer Klasse vornimmt (mit extend ableitet), sollte man mit protected arbeiten. Fehlt der Zugriffsmodifizierer, das ist das Element immer als public anzusehen. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -36- 6.2. Getter und Setter Getter und Setter sind Methoden, die die Eigenschaften eines Objektes schützen sollen. Diese Methoden können Fehlerbehandlungen oder Umwandlungen durchführen. public class Kreis { private int Radius=0; //Getter public int getRadius () { return Radius; } //Setter public void setRadius (int val) { if(Radius > 0){ this. Radius = val; } } } Die eigentliche Eigenschaft ist private, also geschützt. Die Getter heißen get<Eigenschaft> und set<Eigenschaft>. Wie man im Beispiel erkennen kann, wird nur dann ein Radius gespeichert, wenn dieser größer 0 ist, also hier wird auf die Eingabe reagiert, und so die Eigenschaft geschützt. 6.3. Konstruktoren Konstruktoren dienen dazu, beim Erstellen des Objektes Aufgaben zu erledigen. Ein Konstruktor heißt immer so wie die Klasse / Objekt selbst. public class Rechteck extends Shape2D { public int Laenge; public int Breite; public Rechteck (int b, int l) { this.Laenge = l; this.Breite = b; } } Im obigen Beispiel werden dem Konstruktor 2 Parameter mit übergeben. Diese Parameter sind die Länge und die Breite des Rechtecks. Das Erstellen des Objektes sieht so aus Rechteck = new Rechteck(12,10); Es sind nun zwingend diese beiden Parameter notwendig. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -37- Man kann aber auch mehrere Konstruktoren schreiben, und so steuern, wie man das Objekt anlegen möchte. public class Rechteck extends Shape2D { public int Laenge; public int Breite; public Rechteck () { } public Rechteck (int b, int l) { this.Laenge = l; this.Breite = b; } } Im obigen Beispiel sieht man 2 Konstruktoren. Man kann nun den einen oder den anderen beim Erstellen des Objektes verwenden. Diesen Vorgang nennt man Überladung einer Methode. Man kann auch den einen Konstruktor aus dem anderen Konstruktor aufrufen. Sehen wir uns dieses Beispiel an Konto(String inhaber) { this.inhaber = inhaber; } Konto(String inhaber, double stand) { this(inhaber); /* Aufruf des Konstruktors Konto(String inh) */ this.stand = stand; } Konto(String inhaber, double stand, boolean gesperrt) { this(inhaber, stand); this.gesperrt = gesperrt; } Mit this() werden hier die anderen Konstruktoren geladen. 6.4. Die static Methode Man kann eine Methode einer Klasse als static definieren, z.B. public class FileManagement { public static String[] ReadDir(String path){ … tu was ... } } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -38- Was ist damit erreicht. Eine static gekennzeichnete Methode, kann per Klassen Namen aufgerufen werden. Das Erzeugen einer Instanz ist nicht mehr nötig. String[] ergebnis = FileManagement.ReadDir(Path); anstatt von FileManagement fm = new FileManagement(); String[] ergebnis = fm.ReadDir(Path); ist ausreichend. 6.5. Mehrfachvererbungen - Interfaces Das Problem: Eine Klasse soll von zwei Vorgängern abgeleitet werden, also eine Mehrfachvererbung. Wie geht das? Das Geheimnis sind Interfaces. Das sind rein abstrakte Klassen, die nur die Aufgabe haben, an Subklassen zu vererben. Schauen wir uns folgendes Beispiel an: Die einzelnen Baumarten sollen sowohl von der abstrakten Klasse Holzarten, als auch von einer Klasse Kostenabrechnung abgeleitet werden. Die Klassen könnten so aussehen public interface kostenrechnung { public double laenge = 0; public double breite = 0; public double hoehe = 0; public abstract void Kosten(); public abstract void Festmeter(); } Vererbt werden folgende Eigenschaften: public interface holzarten { public double preis = 0; public byte lieferzeit = 0; public String bezeichnung = ""; } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -39- Jetzt wollen wir, das alle Holzarten von beiden Klassen, also holzarten und kostenrechnung erben. public class holz implements kostenrechnung, holzarten{ public double Kosten(){ return Volumen() * preis; } public double Volumen(){ return laenge * breite * hoehe; } } Und schon sind wir fertig. Getrennt durch einen Beistrich kann man beliebig viele Interfaces für eine Klasse bekommen. 6.6. Verwendung der UML - Unified Modeling Language Wenn das Modul UML installiert ist, kann man diese Sprache verwenden um ein Rohgerüst von Klassen zu erzeugen. Man zeichnet einfach die Klassen und kann sich auf Knopfdruck den Quellcode erstellen lassen. Dazu muss man ein bestehendes Projekt angeben, in dem die *.java Dateien erstellt werden. Zusätzlich werden auch die entsprechenden Get- und SetMethoden erstellt (siehe dazu 6.2. Getter und Setter). Das obige Beispiel sieht dann so aus: Abbildung 1: UML Modell aus Netbeans Der Pfeil bedeutet die Abhängigkeit der Klassen zueinander. Der Pfeil zeigt dabei auf die Mutterklasse. Mit einem Rechten Mausklick und Generate Code, wird die Java Datei erstellt. Diese sehen dann so aus. public class Shape2D { Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -40- private int Linie; private int Linienfarbe; public Shape2D () { } public int getLinie () { return Linie; } public void setLinie (int val) { this.Linie = val; } public int getLinienfarbe () { return Linienfarbe; } public void setLinienfarbe (int val) { this.Linienfarbe = val; } public abstract void Zeichnen () { } public abstract void Flaeche () { } public abstract void Umfang () { } } und public class Rechteck extends Shape2D { private int Laenge; private int Breite; public Rechteck () { } public void Diagonal () { } public int getBreite () { return Breite; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -41- } public void setBreite (int val) { this.Breite = val; } public int getLaenge () { return Laenge; } public void setLaenge (int val) { this.Laenge = val; } public void Zeichnen () { } public void Umfang () { } public void Flaeche () { } } Also bekommt man ein Grundgerüst, das nur noch aus programmiert werden muss! 7. Fragen wir Dr. Java, Good to know 7.1. Bildschirmauflösung abfragen Wie zentriere ich ein Fenster? Wie passe ich ein Fenster an den Monitor an? Nun so Dimension screenResolution = sys.getScreenResolution(); MainForm f = new MainForm(); Dimension fsize = new Dimension( (int)(screenResolution.width*0.75), (int)(screenResolution.height*0.9) ); f.setSize(fsize); f.setVisible(true); Zuerst frage ich die Bildschirmauflösung ab, und dann kann ich wie hier gezeigt, die Größe des Fensters an den Monitor anpassen. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -42- 7.2. Dynamisches Erstellen von Elementen Was tun, wenn zur Laufzeit dynamische Elemente erzeugt werden müssen? Als Beispiel wollen wir einige Buttons dynamisch erzeugen. Collection btnList = new LinkedList<JButton>(); /*Erstellen von 10 Buttons*/ for(int i=0; i<10; i++){ JButton btn = new Jbutton("Button"+i); btn.setVisible( true ); /*KlickMethode per Listener zuweisen*/ btn.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ String buttonText = e.getActionCommand(); } }); /*Button zur Collection hinzufügen*/ btnList.add(btn); /*der Form zuordnen*/ this.add(btn); /*neuzeichnen auslösen*/ this.setVisible(true); 7.3. Warum erfolgt kein Repaint einer Komponente? Wenn dir das passiert, dann denke an folgendes • mache ein revalidate() • mache ein repaint() z.B. hast du ein Panel das sich neu zeichnen muss, das macht du also so PanelKlassen.revalidate(); PanelKlassen.repaint(); Nun sollte es klappen! 8. Threads mit Java 8.1. Threads über das Interface Runnable Threads können über ein so genanntes Interface erzeugt werden. interface java.lang.Runnable Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -43- Dieses Interface bietet nur die run() Methode und lässt den Thread parallel zum Hauptprogramm ablaufen. public class DateCommand implements Runnable { @Override public void run(){ for ( int i = 0; i < 20; i++ ) System.out.println( new java.util.Date() ); } } in Arbeit 8.2. wait() und notify() Manchmal möchte man auf das Ende eines Threads warten, weil dieser z.B. sehr lange etwas berechnen muss. In diesem Fall hält man den aufrufenden Thread an, und schickt diesen schlafen. Hier ein Beispiel (Quelle: www.tutorials.de/java/): Der MasterThread wartet solange, bis der ClientThread ihn wieder aufweckt. public class MasterThread extends Thread { private ExecutorService service = Executors.newCachedThreadPool(); @Override public void run() { System.out.println("MasterThread start"); synchronized (this) { service.execute(new ChildThread(this)); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("MasterThread ende"); } class ChildThread implements Runnable { private MasterThread masterThread; ChildThread(MasterThread masterThread) { this.masterThread = masterThread; } @Override Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -44- public void run() { try { System.out.println("ChildThread start"); System.out.println("ChildThread ende"); } finally { // Sicherstellen, dass Parent geweckt wird synchronized (masterThread){ masterThread.notify(); } } } } 8.3. Zugriff auf Daten aus einem Thread heraus Um auf eine gemeinsame Klasse aus Threads heraus zugreifen zu können, muss der Zugriff threadsicher sein. Wenn ein Thread gerade auf sagen wir eine Variable zugreift, muss ein anderer Thread warten bis er dran ist. Das erreicht man mit dem synchronized() Statement. public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } Im Thread selbst, spricht man die obigen Methoden so an synchronized(counter){ counter.increment(); } Das synchronized() Statement macht den Zugriff threadsischer, d.h. das ein anderer Thread solange wartet bis er dran ist. 8.3.1. Synchronisieren mit einem Objekt Man kann auch so einen Zugriff starten Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -45- public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } } 8.4. Executors Liefern ein Thread Management und ist nützlich für größere Anwendungen. Mit Zum Beispiel Threadpools, kann man eine fixe Anzahl von Threads arbeiten lassen. Der Executor startet dann automatisch die nächsten anstehenden Threads. Man muss sich also nicht um die Abarbeitung der Threads mehr kümmern. Sehen wir uns ein Beispiel an //Anzahl der CpU Cores ermitteln int processors = Runtime.getRuntime().availableProcessors(); //Thread Pool ExecutorService executor =Executors.newFixedThreadPool(processors); //100 Bilder laden un umrechnen for(int i=0; i<100; i++){ ThumbLoadWorker thumbworker = new ThumbLoadWorker( new StaticThumbLoader(), filename[i]); executor.submit(thumbworker); } //keine Threads werden mehr akzeptiert executor.shutdown(); Hier werden 100 Bilder in Threads geladen und zu einem Thumbnail verkleinert. Es arbeiten immer so viele Threads, so viele CPU Cores der Computer hat. Die fertigen Thumbnails werden über das statische Objekt StaticThumbLoader weiter verarbeitet. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -46- 9. Grafische Anwendungen mit SWING Grafische Oberflächen programmieren wir mit der SWING Oberfläche. Dazu erstellt man eine entsprechende Desktop Application. Es steht nun eine grafische (Design) und eine Quellcode (Source) Oberfläche bereit. Im Design Modus kann man Buttons, Panels und andere Steuerelemente auf dem Fenster platzieren, z.B. Das Aussehen kann man für jedes Steuerelement über die Eigenschaften einstellen. 9.1. Mehrzeilige Labels Sind kein Problem, wenn man genau die Hilfe liest. Stellt man <html> vor den Text, kann man den Text mit html-Tags behandeln. Also zum Beispiel ergibt jLabel3.setText("<html>Hier stellst du Parameter der Fotogallerie ein<br>alle die du möchtest"); einen zweizeiligen Label. 9.2. Actions und Events Jedes Steuerelement kann diverse Aufgaben bekommen. Nehmen wir als Beispiel einen Button. Dessen Eigenschaften und Events sehen so aus: Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -47- Events sind so was wie: Maus ist über dem Steuerelement, Angeklickt u.s.w. Klickt man in das Feld <none> eines Events, wird ein Name vorgeschlagen. Bestätigt man den Namen mit Enter, springt man an die entsprechende Stelle im Quellcode. mit dem Quellcode private void jButton1ActionPerformed(java.awt.event.ActionEventevt) { // TODO add your handling code here: int test = 0; System.exit(0); } 9.3. Mausereignisse erstellen Mausereignisse werden als erstes per Interface „geladen“. public class AnimApplet extends Applet implements Runnable, MouseListener, MouseMotionListener { Je nach dem, welche Ereignisse man benötigt, wählt man ein Interface aus. Mit dem Netbeans Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -48- Editor kannst du alle Ereignisse auch per grafischer Oberfläche aktivieren, aber im Prinzip passiert genau das, was nun beschrieben wird. Nehmen wir an, wir haben ein Panel erstellt, das auf Mausereignisse reagieren soll: mainPanel = new Jpanel(); this.add(mainPanel, BorderLayout.CENTER); mainPanel.addMouseMotionListener(new MausMove()); mainPanel.addMouseListener(new MausPanel()); Wie man sieht, werden hier zwei unterschiedliche Maus-Listener verwendet, denen zwei Klassen zugewiesen werden, nämlich: MausMove() und MausPanel(). Diese Inline Klassen, werden innerhalb der aktuellen Klasse erzeugt. class MausMove implements MouseMotionListener{ public void mouseDragged(MouseEvent e){ } public void mouseMoved(MouseEvent e) { } } und class MausPanel implements MouseListener { public void mouseClicked(MouseEvent e) { } public void mousePressed(MouseEvent e) { } } Netbeans hilft uns hier, und setzt auf Knopfdruck alle möglichen Mausereignisse ein. Und nun braucht man nur noch in die entsprechenden Klassen eintragen, was passieren soll, wenn dieses Ereignis eintritt. 9.4. Layout Manger Die Ausrichtung von Elementen kann man mit 3 Methoden steuern 1. FlowLayout: Zeilenweise Anordnung 2. BorderLayout: Anordnung in den vier Himmelrichtungen (Rahmen) und einem Mittelbereich 3. GridLayout: Anordnung in einem Gitter mit n gleichgroßen Zellen 9.4.1. FlowLayout this.setLayout(new FlowLayout()); JButton MyButton1 = new JButton("MyButton 1"); JButton MyButton2 = new JButton("MyButton 2"); Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -49- JButton MyButton3 = new JButton("MyButton 3"); add(MyButton1); add(MyButton2); add(MyButton3); liefert dieses Ergebnis Abbildung 2: FlowLayout FlowLayout fügt zeilenweise in die Oberfläche ein, und jeweils zentriert. Ist die erste Zeile voll, wird die nächste Zeile eröffnet. 9.4.2. BorderLayout initComponents(); this.setLayout(new BorderLayout()); JButton MyButton1 = new JButton("MyButton 1"); JButton MyButton2 = new JButton("MyButton 2"); JButton MyButton3 = new JButton("MyButton 3"); add(MyButton1, BorderLayout.NORTH); add(MyButton2, BorderLayout.SOUTH); add(MyButton3, BorderLayout.LINE_END); liefert Abbildung 3: BorderLayout Hier kann man in die vier Himmelsrichtungen ausrichten. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans 9.4.3. Seite -50- GridLayout kein Beispiel, Verwendung wie die anderen Layouts 9.4.4. LayoutManager deaktivieren mit setLayout(null); 9.4.5. Weitere Beispiele zum Layout public class Flow2 extends Applet{ public void init() { setLayout(new FlowLayout(FlowLayout.RIGHT)); for (int i = 0; i < 4; i++) add(new Button("Button #" + i)); } } Ein Beispiel um einen Button auszurichten setLayout(new BorderLayout); Start = new Button("Start"); add(Start, BorderLayout.CENTER); 9.5. Dialoge 9.5.1. FileOpen Dialog Hierzu gibt es ein eigenes Objekt, das man z.B. bei einer Button Action anwenden kann private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) { JFileChooser fs = new JfileChooser(); int returnVal = fs.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { File file = fs.getSelectedFile(); } else { System.out.println("File access cancelled by user."); } } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -51- Das Ergebnis sieht dann in etwa so aus Den angezeigten Dateityp kann man mit einem Filter einstellen, das könnte dann so aussehen ExampleFileFilter filter = new ExampleFileFilter(); filter.addExtension("jpg"); filter.addExtension("gif"); filter.setDescription("JPG & GIF Images"); chooser.setFileFilter(filter); 9.6. Die Sache mit den Pfaden, Icons, Images und Dateien Öfters kommt es vor, das man ein Image aus einem Verzeichnis laden möchte. Wie mache ich das zur Laufzeit? Nehmen wir an, wir wollen aus dem Package rimages das Bild bird24.png als Icon für unser Fenster verwenden. Wir bekommen hier eine getResource() Methode zur Verfügung gestellt. Das ist nicht der einzige Weg, aber es reicht uns hier, diese Möglichkeit zu sehen. Und so geht es URL imgURL = getClass().getResource( "/rimages/bird24.png" ); this.setIconImage( (new ImageIcon(imgURL)).getImage()); Damit haben wir die Möglichkeit, Images, Icons oder alle anderen Dateien aus einem Package zu Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -52- laden. Daher gilt ab jetzt folgender Ratschlag: Dateien die man zur Laufzeit einbinden möchte, sollten immer in einem Package liegen! 9.7. Die Sache mit dem JAR-File Wenn allerdings aus einem JAR File der Befehl getClass().getResource() verwendet wird, funktioniert das nicht! (bin mir nicht ganz sicher) Es funktioniert dann nur getClass().getResourceAsStream(), was einen InputStream liefert. Das sollte man beachten und auch ausführlich testen! 10. SWING Komponenten im Detail 10.1. JTable Model Das TableModel definiert die Daten, die die Tabelle anzeigt. Das Model liefert Aufschluss darüber, welche Werte eine Zelle hat, wobei es auch die Anzahl der Spalten und Zeilen definiert. Abhängig von Zeile und Spalte entscheidet das Model darüber, ob die Zelle editierbar ist, wobei der erfolgreich geänderte Wert mittels setValue(Object value) ins Model zurückgeschrieben wird. Wichtig ist die Zeile types, denn hier wird angegebne welche Daten dargestellt werden. z.B. eine Tabelle TabellePersonen extends JTable könnte so aussehen public TabellePersonen(Object[] columnNames, Object[][] data) { super(); /* Was wird gespeichert */ setModel(new DefaultTableModel(data,columnNames){ Class[] types = new Class [] { Integer.class, String.class, String.class, String.class, String.class }; /* Editierbar? */ boolean[] canEdit = new boolean [] { false, true, true, false, false}; @Override public Class getColumnClass(int columnIndex) { return types [columnIndex]; } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -53- @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return canEdit [columnIndex]; } }); 10.2. Auf Ereignisse reagieren Wenn sich etwas in der Tabelle ändert möchte man darauf reagieren, da könnte so ablaufen /* Daten in der Tabelle haben sich geändert */ this.getModel().addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { System.out.println(e); } }); /* welche Zeile ist selektiert? */ this.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if(e.getValueIsAdjusting()) return; } }); 10.3. Zellen darstellen un bearbeiten Oft möchte man eine Zelle bestimmt darstellen, z.B. mit einem Button, oder man möchte auf eine Eingabe reagieren. Dazu bnietet die Tabelle zwei Dinge an 1. Renderer, der die Darstellung der Zelle übernimmt 2. Editor, der die Bearbeitung der Zelle übernimmt. 10.3.1. Ein Renderer Angenommen wir haben so ein Model setModel(new DefaultTableModel(data,columnNames){ Class[] types = new Class [] { Integer.class, String.class, String.class, String.class, String.class }; Dann kann man für eine Klasse einen eigenen Renderer angeben, z.B. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -54- this.setDefaultRenderer(Integer.class, new ZahlenRenderer()); this.setDefaultRenderer(Object.class, new IrgendwasRenderer()); 10.4. Ein konkretes Beispiel Angenommen eine Zelle soll einen Button bekommen. Wie macht man das? Wir brauchen für die Zelle einen Renderer und einen Editor. Die Tabelle wird so angelegt setModel(new DefaultTableModel(data,columnNames){ Class[] types = new Class [] { Integer.class, String.class, String.class, String.class, Note.class, Aktionen.class}; Wir legen hier eine eigene Klasse Aktionen an. Sie dient eigentlich nnur zur Identifikation der Klasse in der Zelle, und kann daher inline, leer definiert werden. private class Aktionen{} Nun können wir den entsprechenden Renderer zuweisen this.setDefaultRenderer(Aktionen.class, new AktionenRenderer()); Wir sehen hier unser Dummy Klasse. Der Renderer selbst sieht so aus private class AktionenRenderer extends JPanel implements TableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) { this.removeAll(); this.setLayout(new FlowLayout(FlowLayout.RIGHT, 4, 0)); JButton btn1 = new JButton(); btn1.setIcon( new ImageIcon(getClass().getResource ("/icons/add.png"))); btn1.setPreferredSize(new java.awt.Dimension(25, 25)); this.add(btn1); return this; } } Dieser Renderer ist von JPanel abgeleitet, das this bezieht sich darauf. Darin können wir nun unseren Button definieren (muss nicht in einem Panel sein, aber warum nicht). Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -55- Nun kommt noch der Editor, mit dem wir auf die Benutzung des Buttons reagieren! Hier muss man beachten, das der Editor wiederum einen neuen Button zeichnet, der sich von dem des Renderes unterscheidet. Am besten übergibt man beiden den selben Button! class AktionenEditor extends JButton implements TableCellEditor { private List<CellEditorListener> listeners = new ArrayList<CellEditorListener>(); public AktionenEditor() { addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { throw new UnsupportedOperationException("Button: Not supported yet."); } }); } @Override public JButton getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column ) { /* Diese Methode wird von der JTable aufgerufen, wenn der Editor angezeigt werden soll */ return this; } @Override public void addCellEditorListener( CellEditorListener l ) { listeners.add( l ); } @Override public void cancelCellEditing() { /* Falls abgebrochen wird, werden alle Listeners informiert */ ChangeEvent event = new ChangeEvent( this ); for( CellEditorListener listener : listeners.toArray( new CellEditorListener[ listeners.size() ] )) listener.editingCanceled( event ); } @Override public Object getCellEditorValue() { /* Button hat keinen Wert */ return null; } @Override /* Immer editierbar, d.h. Button immer anklickbar */ public boolean isCellEditable( EventObject anEvent ) { return true; } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -56- @Override public void removeCellEditorListener( CellEditorListener l ) { listeners.remove( l ); } @Override public boolean shouldSelectCell( EventObject anEvent ) { return true; } @Override public boolean stopCellEditing() { /* Ansonsten werden die Listener vom stop unterrichtet */ ChangeEvent event = new ChangeEvent( this ); for( CellEditorListener listener : listeners.toArray( new CellEditorListener[ listeners.size() ] )) listener.editingStopped( event ); return true; } } Diese Klasse ist etwas größer, man kann aber im Prinzip alles kopieren! 10.5. Renderer und Editor in einer Klasse Im obigen Beispiel gab es zwei verschiedene Buttons für Editor und Renderer. Besser ist es nur einen Button zu haben, und alles in einer Klasse zusammenzufassen. In der Tabelle wird so der Button aktiviert ButtonInColumn btnCol = new ButtonInColumn(this, mybtn, delete, 4); this.setDefaultRenderer(Aktionen.class, btnCol); this.setDefaultEditor(Aktionen.class, btnCol); Die Klasse ButtonInColumn bekommt dabei übergebn • die Tabelle • den Button der angezeigt wird • die Action die beim Klicken ausgeführt wird • die Spalte in der Tabelle Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -57- Änderungen an Tabelle this.getModel().addTableModelListener(new TableModelListener() { @Override public void tableChanged(TableModelEvent e) { System.out.println(e); } }); 11. GDI 11.1. Zeichnen in einem Panel Wo man zeichnet ist relativ egal. Ich zeichne meistens in ein Panel, weil ich das Panel auf der Seite beliebig positionieren kann. Dazu erstellen wir eine eigene Klasse die so aussieht package MyPanel; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.image.BufferedImage; import javax.swing.*; public class DrawPanel extends Jpanel{ @Override protected void paintComponent( Graphics g ){ //hier wird gezeichnet } } Wir leiten also vom JPanel ab, und überschreiben dessen Paint Methode. Die Paint Methode wird automatisch aufgerufen, um das brauchen wir uns nicht kümmern. Schreiben wir hier unsere Zeichenroutinen hinein, zeichnen wir innerhalb des Panel's. Das war's auch schon, so einfach ist das :) . 11.2. Transformationen Der Koordinatenursprung von Objekten liegt immer links oben. Möchte man z.B. den Koordinatenursprung in die Mitte des Objektes verschieben, kann man eine Transformation wie folgt verwenden public void paintComponent(Graphics gIn){ Graphics2D g = (Graphics2D)gIn.create(); g.translate(getWidth() / 2, getHeight() / 2); g.rotate(30.0 * Math.PI / 180.0); g.setFont(new Font("Sans", Font.BOLD, 24)); Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -58- g.drawText("M"); g.destroy(); } Hier wird mit dem Graphics2D Objekt der Koordinatenursprung in die Mitte der Komponente geschoben, und das Koordinatensystem um 30° gedreht. Das Ergebnis sieht so aus 11.3. Affine Transformation Man kann auch dieses Objekt verwenden, um eine Transformation als ein „Makro“ zu speichern. AffineTransform a = new AffineTransformgetTranslateInstance (getWidth() / 2, getHeight() / 2); public void paintComponent(Graphics gIn){ Graphics2D g = (Graphics2D)gIn.create(); g.setTransform(a); g.setFont(new Font("Sans", Font.BOLD, 24)); g.drawText("M"); g.destroy(); } Weitere Informationen findest du hier http://java.sun.com/j2se/1.5.0/docs/api/java/awt/geom/AffineTransform.html. 11.4. Punktierte Linie zeichnen Als Beispiel in der Paint Methode g2.setColor(new Color(c, c, c)); Stroke stroke = new BasicStroke(1,BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { 2, 2 }, 0); g2.setStroke(stroke); … Linie zeichnen … 12. Erstellen von Java Applets für Webseiten http://java.sun.com/docs/books/tutorial/deployment/applet/ Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -59- 12.1. Grundlagen Applets werden in Webseiten dargestellt, was die Möglichkeit bietet, JAVA Programme im Internet zu verbreiten. Es gibt aber einige Einschränkungen zu einem vollwertigen Projekt, immerhin wird ein Programm aus dem Internet auf den Computer geladen, und das ist eine Sicherheitslücke. Daher gilt • Applets dürfen nicht ohne weiteres auf Dateien des Computers zugreifen • Ladezugriffe aus dem Internet sind nur auf den Server zulässig, von dem das Applet geladen wurde Der Aufruf eines Applets sieht so aus <applet code=“HalloWWW.class“ width=“200“ height=“300“> </applet> oder so <applet width="300" height="433" code="Nature.class" align="left" hspace="20" vspace="12"> <param name="accumulate" value="yes"> <param name="background" value="FFFFFF"> <param name="backimg" value="pixel.gif"> <param name="DeveloperInfo" value="Michael Chancey Jr."> <param name="speed" value="75"> <param name="foreground" value="FFFFFF"> <param name="graphic" value="winterbild.jpg"> <param name="randomdir" value="yes"> <param name="season" value="winter"> <param name="fallcount" value="400"> </applet> Ein Applet hat statt dem Haupteinstiegspunkt main() die Methoden init(), start(), paint(), stop() und destroy(). Diese Methoden werden vom Browser aus gestartet und sind relativ selbsterklärend. 12.2. Der HtmlConverter Möchte man unabhängig von diversen Browsertypen ein Applet korrekt einbinden, dann findet man im bin Ordner des JDK ein Programm mit Namen HtmlConverter.exe. ??? Bild Man gibt hier den Pfad zur HTML Seite an (üblicherweise nach dem Build Befehl im Ordner build/), und der Rest wird automatisch erledigt! Der Html Code wird dabei sehr unübersichtlich, liefert aber ein passendes Ergebniss. 12.3. Applets und jar-Dateien Für größere Projekte oder Datenmengen bietet sich das jar-Format an (vergl. 3.3 Die Struktur der Dateien). Das ist im Prinzip nichts anderes als ein zip File von allen nötigen Daten. Jar kann von Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -60- der Konsole aus gestartet werden. Der Aufruf des Applets sieht dann so aus <applet code=“HalloWWW.class“ archive=“Pack.jar“ width=“200“ height=“300“></applet> 12.4. Erstellen und testen eines Applets Möchte man ein komplett neues Projekt eröffnen, oder doch eine bestehende Anwendung in ein Applet einbinden? Wir erstellen ein neues Projekt vom Typ Java Class Library. In der Projektverwaltung erstellen wir mit New → Others erstellen wir in eine • Applet Class • JApplet Class • Japplet Form (hier erhältst du den Form Designer) etc So sieht der Projektordner aus. Wenn du die den Quellcode ansiehst, erkennst du, das es eine Methode init() gibt. Diese Methode wird vor dem anzeigen des Applets geladen. Daher bereitet man hier alles vor, was für den Betrieb nötig ist. public void init() { /*TODO start asynchronous download of heavy resources*/ } /*TODO overwrite start(), stop() and destroy() methods*/ Weiters sehen wir hier einen Hinweis auf weitere Methoden des Applets. Diese kann man, wenn man sie benötigt, überschreiben und verändern. 12.4.1. Projekteigenschaften erstellen Bevor wir den ersten Test laufen lassen können, müssen wir noch die Eigenschaften des Projektes etwas verändern. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -61- Der Webstart muss so angepasst werden. Das Allow Offline kann man aktivieren, wenn man möchte. Wichtig ist die CodeBase, hier muss man den Speicherort am Webserver einstellen! Im Beispiel ist das http://www.bgbaden-frauen.ac.at/ext/kochapplet/. 12.5. Testen des Projektes Das Java Network Launching Protocol (JNLP) ist ein XML-Format, das festlegt, wie Anwendungen per Java Web Start aufgerufen werden. JNLP-Dateien enthalten Informationen wie den Ablageort von JAR-Dateien, den Namen der Hauptklasse einer Anwendung und zusätzliche Parameter für das aufzurufende Programm. Ein korrekt konfigurierter Webbrowser übergibt JNLP-Dateien an die Java-Laufzeitumgebung, die dann ihrerseits die Anwendung auf den PC des Anwenders herunterlädt und startet. Zum testen lass die die Files deines Projektes anzeigen. Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -62- Mit dem Befehl Build F11 lassen wir unser Projekt erstellen. Im Ordner dist/ erhält man dann das gepackte JAR-File, das html-Dokument und die *.jnlp Datei. Optional: Im bin Ordner des JDK (z.B. C:\Programme\JDK\bin) findet man den HtmlConverter.exe. Mit dessen Hilfe kann man die HTML Datei noch für alle Browsertypen anpassen. Man gibt die html-Datei aus dem /dist Ordner an. 12.6. Automatischr Größenanpasseung des Applets an das Fenster <body onresize="resize()" onload="resize()" topmargin="0" leftmargin="0" marginwidth="0" Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -63- marginheight="0"> <script language="JavaScript" type="text/javascript"> function resize(){ var w_newWidth,w_newHeight; var w_maxWidth=1600, w_maxHeight=1200; if (navigator.appName.indexOf("Microsoft") != -1){ w_newWidth=document.body.clientWidth-15; w_newHeight=document.body.clientHeight-15; }else{ var netscapeScrollWidth=50; w_newWidth=window.innerWidth-netscapeScrollWidth; w_newHeight=window.innerHeight-netscapeScrollWidth; } if (w_newWidth>w_maxWidth) w_newWidth=w_maxWidth; if (w_newHeight>w_maxHeight) w_newHeight=w_maxHeight; document.myApplet.setSize(w_newWidth,w_newHeight); window.scroll(0,0); } window.onResize = resize; window.onLoad = resize; </script> <applet name="myApplet" width="300" height="300"> <param name="jnlp_href" value="launch.jnlp"/> </applet> Bufferd Image http://staff.science.uva.nl/~heck/JAVAcourse/ch6/s2.html 13. Java Documentation erstellen Mit einem rechten Mausklick auf ein Projekt kann man einen Dokumentation aller Programmteile anfertigen lassen. Das ist eine gewöhnliche HTML Seite. Wichtig ist dabei, dass alle Programmteile bereits beim Programmieren dokumentiert wird, und zwar auf eine bestimmte Art und Weise. Um die Dokumentation einzuleiten schreibt man /** Ein Beispiel könnte so aussehen /** * Der Port der Tcp Verbindung */ private int port = 0; Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -64- /** * Liefert den Port des Servers zurück * @return port Nummer */ public int getPort(){ return port; } /** * Setzt den Port der Serveranwendung * @param _port Nummer des Ports */ public void setPort(int _port){ this.port = _port; } 14. Virtual Machine steuern Oft reicht z.B. der reservierte Speicher der VM nicht aus. Dann kann man mit diversen Parametern die VM steuern.Das passiert bei Netbeans in den Eigenschaften des Projektes -Xmx1024m.................reserviert 1024 Mbyte für die VM Eine ausführliche Beschreibung aller Parameter, findest du im Internet! 15. Netzwerkprogrammierung Wie funktioniert denn das? Eine gute Anlaufstelle für erste Informationen ist hier http://download.oracle.com/javase/tutorial/networking/index.html Im folgenden zeige ich, wie man mit Sockets programmiert. Der Ablauf einer Kommunikation zwischen Server <> Client sieht so aus Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -65- Start Server wartet auf eine Verbindung mit Client Client verbindet sich mit Server Server verarbeitet Daten u. sendet Antwort Client sendet Daten ja ? Weitere Anfragen des Clients? nein Client beendet die Verbindung Die Daten werden zu den Sockets per Streams geschickt. So kannst du z.B. sehr leicht Strings verschicken, nur was tust du, wenn du String, Integer, Date etc. versenden möchtest? Wir erstellen uns ein Übermittlungsprotokoll und halten das ein. Und zwar senden wird ByteArrays über die Sockets (in JAVA würde auch Serialisieren mit Object*Streams funktionieren). 15.1. Datenpakete - TcpPackages Die Kommunikation erfolgt über Datenpakete. Es gelten folgende Bezeichnungen: GL {4 Bytes} T {1 Byte} D {x Bytes} ... Gesamtlänge des Daten-Paketes ... Typ des Paketes bestimmt ... die Daten 15.2. Paketarten 15.2.1. Flag – Paket: (3 Bytes) PL F Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -66- 16. SWING und Update von Komponenten Es stellt sich z.B. das Problem, dass gleichzeitig ein Algorithmus ablaufen, und ein Fortschittsbalken gezeichnet werden soll. Man kann dies mit Multithreading, also dem Aufteilen des Programmes in mehrere Prozesse, erreichen. Da der Aufbau von Swing (bzw. AWT) es nicht erlaubt, Teile der graphischen Oberfläche in einen anderen Thread auszulagern, muss man in jedem Fall den Algorithmus auslagern. Und da Swing nicht threadsicher ist, darf man von dem ausgelagerten Algorithmus eigentlich nicht auf den Fortschrittsbalken zugreifen! Ab JRE6 gibt es den SwingWorker, der genau das für uns macht. Hier ein einfaches Beispiel für einen Label final JLabel label; class MeaningOfLifeFinder extends SwingWorker<String, Object> { @Override public String doInBackground() { return findTheMeaningOfLife(); } @Override protected void done() { try { label.setText(get()); } catch (Exception ignore) { } } } (new MeaningOfLifeFinder()).execute(); oder public void Invoke(final String msg, final Color col){ if(output != null){ javax.swing.SwingUtilities.invokeLater(new Runnable() { @Override public void run() { output.append(msg, col); } }); } } Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -67- 17. Zwischenablage und JAVA Die Zwischenablage ist in Java durch ein Clipboard-Objekt repräsentiert. Es gibt bei grafischen Oberflächen ein System-Clipboard, welches sich über das Toolkit-Objekt erfragen lässt. Clipboard systemClip = Toolkit.getDefaultToolkit().getSystemClipboard(); DataFlavor beschreibt das Format der Daten in der Zwischenablage Die Klasse DataFlavor beschreibt das Format der Daten, die in der Zwischenablage liegen. Die Klasse kommt neben dem Einsatz in der Zwischenablage auch bei Drag&Drop-Operation und auch beim Dateisystem vor. public static void main( String args[] ) throws Exception { Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); Transferable transferData = systemClipboard.getContents( null ); DataFlavor dataFlavor[] = transferData.getTransferDataFlavors(); Object content = transferData.getTransferData( dataFlavor[1] ); System.out.println( content ); } http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=412 https://rz-static.unihohenheim.de/anw/programme/prg/java/tutorials/javainsel4/javainsel_15_028.htm#Rxx365java150 28040005531F039100 import java.awt.datatransfer.*; import java.awt.image.*; public DataFlavor[] getTransferableDataFlavors() { Mag. Stefan Hagmann & Mag. Thomas Steiner JAVA mit Netbeans Seite -68- DataFlavors flavors = {DataFlavor.imageFlavor, DataFlavor.stringFlavor}; return flavors; } Mag. Stefan Hagmann & Mag. Thomas Steiner