Kapitel 2 Das erste Programm 2 Das erste Programm Anstatt nun lange über die Programmiergrundlagen von Java zu reden, stürzen wir uns gleich voll rein und erstellen das erste Java-Programm, natürlich mit Unterstützung des JBuilders! Falls Sie noch nie in Java programmiert haben, müssen Sie deswegen jetzt keine weichen Knie bekommen. Sie werden feststellen, dass wir für unser erstes Programm nicht eine einzige Zeile Code selbst aufsetzen müssen. Das erledigt alles der JBuilder für uns! Sie lernen in diesem Kapitel, ✘ wie ein neues Projekt erzeugt wird, ✘ wie die grundlegende Struktur eines Java-Programms aussieht, ✘ wie man mit Komponenten arbeitet, ✘ wie die RAD-Umgebung des JBuilders funktioniert. 2.1 Am Anfang steht immer ein Projekt Legen wir also los. Sie sitzen entspannt vor Ihrem PC und sehen hoffentlich eine Windows-Oberfläche, sei es nun Windows 98/NT oder eine X-Windows Variante. Starten Sie nun den JBuilder und warten Sie ein oder zwei Minütchen, bis auf dem Bildschirm wieder Ruhe eingekehrt ist. TIPP Sie sollten nun die JBuilder-Oberfläche sehen: eine Menüleiste, darunter eine Symbolleiste (auch Toolbar genannt) und unterhalb davon zwei Fens- 31 Kapitel 2 Das erste Programm ter: das linke ist das Projektfenster und das rechte nennt sich Inhaltsfenster. Wenn Sie sich an die Standardinstallation gehalten haben, befinden sich im Projektfenster schon vier Einträge (Welcome.jpr oder Welcome.jpx, Welcome.html, WelcomeApp.java und WelcomeFrame.java). Wenn Sie beispielsweise auf WelcomeApp.java doppelklicken, erscheint im Inhaltsfenster der Quelltext, der zu WelcomeApp.java gehört. Bringen wir nun etwas Klarheit in das Ganze. Ein Java-Programm besteht in der Regel aus mehreren Dateien, im Wesentlichen den Dateien mit dem Quellcode (sie haben die Endung .java). Vielleicht braucht das Programm auch Bilder oder Klangdateien; diese Dateien gehören dann natürlich auch dazu. Um mit dieser Vielzahl von Dateien besser umgehen zu können, werden beim JBuilder alle benötigten Dateien eines Programms zu einem Projekt zusammengefasst. Die Informationen über ein Projekt legt der JBuilder selbst in einer besonderen Datei ab, der Projektdatei (Endung .jpr oder .jpx), deren Inhalt im Projektfenster angezeigt wird. Das Welcome-Projekt, mit dem uns der JBuilder begrüßt, besteht aus drei Dateien: ✘ einer HTML-Datei (das sind die typischen Webdokumente, die Sie aus dem Internet kennen) mit Informationen und einer Beschreibung des Programms und ✘ zwei Java-Dateien mit Quellcode. Schauen Sie sich bei Gelegenheit das Welcome-Projekt mal näher an und spielen Sie damit herum. Zur Einarbeitung in den JBuilder wollen wir aber auf das Begrüßungsprojekt verzichten und uns ein eigenes Projekt erstellen. Übung 1: Ein eigenes Projekt anlegen Schließen Sie zuerst das aktuelle Projekt Welcome.jpr (im Menü DATEI finden Sie den nötigen Befehl PROJEKTE SCHLIESSEN). 1. Rufen Sie im Menü DATEI den Eintrag NEUES PROJEKT auf. Es erscheint das Dialogfenster des Projekt-Experten. Auf der ersten Seite des Assistenten sollten Sie folgende Angaben machen: ✘ den Projektnamen (beispielsweise ErstesProjekt) ✘ den Projekttyp (wählen Sie hier JPR; JPX ist ein XML-basiertes Format und hauptsächlich für Projekte der Enterprise-Edition gedacht) ✘ den Pfad zu dem Ordner, in dem die Projektdateien gespeichert werden sollen (wenn Sie wollen, können Sie auch die Vorgabe beibehal- 32 Am Anfang steht immer ein Projekt ten; existiert das angegebene Verzeichnis noch nicht, wird es vom JBuilder angelegt) ✘ die Option PROJEKTBEMERKUNGSDATEI ERZEUGEN aktivieren. Abb. 2.1: Neues Projekt anlegen Wenn Sie mit früheren JBuilder-Versionen arbeiten, sind die Dialogfenster des Projekt-Experten unter Umständen anders aufgebaut. Pfad und Projektverzeichnis müssen Sie dann eventuell getrennt angeben, beispielsweise: C:\JBProjekte\Kapitel02 und ErstesProjekt. 2. Wenn Sie auf WEITER klicken, gelangen Sie zur zweiten Seite des Projekt-Experten, deren Optionen Sie nicht zu bearbeiten brauchen. Interessanter wird es auf der dritten Seite (in Version 3.5 die zweite Seite), auf der Sie Angaben zum Autor und zur Beschreibung des Projekts machen können. Die entsprechenden Informationen überträgt der JBuilder in die HTML-Bemerkungsdatei des Projekts (die man mit ein wenig HTML-Kenntnissen auch nachträglich bearbeiten und anpassen kann). 3. Klicken Sie zum Schluss auf FERTIGSTELLEN. Im Projektfenster sehen Sie den Aufbau des Projekts ErstesProjekt. Als übergeordneter Knoten des Projekts wird die Projektdatei die ErstesProjekt.jpr aufgeführt. Darunter werden die einzelnen Dateien des Projekts aufgelistet. Unser Projekt enthält derzeit nur eine HTML-Datei namens ErstesProjekt.html zur Beschreibung des Projekts. 33 Kapitel 2 Das erste Programm Abb. 2.2: Das neu angelegte Projekt Wenn Sie im Projektfenster auf den Knoten der HTML-Datei doppelklicken, erscheint im Inhaltsfenster die Beschreibung, die Sie selbst eingegeben haben. Den Quellcode, also das eigentliche HTML-Format können Sie anschauen (oder auch ändern), wenn Sie im Inhaltsfenster das Register QUELLE auswählen. Probieren Sie es mal aus! Beim Umschalten werden Sie feststellen, dass unter dem Projektfenster plötzlich noch ein Fenster aufgetaucht ist: das Strukturfenster. Es veranschaulicht die hierarchische Struktur der aktuellen Datei, die im Inhaltsfenster angezeigt wird. Im Moment ist dies aber für uns noch nicht wichtig. Übung 2: Ein Anwendungsgerüst hinzufügen Bisher haben wir nur eine Beschreibungsdatei in unserem Projekt. Das ist natürlich nicht sonderlich befriedigend. Fügen wir also den ersten JavaQuellcode hinzu. 4. Rufen Sie im Menü DATEI den Eintrag NEU und wählen Sie aus der erscheinenden Objektgalerie das Symbol ANWENDUNG aus. Es erscheint der Anwendungs-Experte. Eine Anwendung ist nichts anderes als ein selbständiges Java-Programm, das von der Festplatte aus aufgerufen werden kann. Weiterhin geht der JBuilder davon aus, dass Sie eine GUI-Anwendung – also eine Anwendung mit grafischer Benutzeroberfläche – erstellen wollen, und wird daher zwei Quelldateien namens Anwendung1.java (für die Anwendung selbst) und Frame1.java (für das Hauptfenster der Anwendung) anlegen. 34 Am Anfang steht immer ein Projekt In jeder dieser Dateien legt der JBuilder ein passende Klasse an, deren Namen Sie selbst vorgeben können. Wir möchten Sie aber bitten, der Einfachheit halber die Vorgabe zu akzeptieren. Auf der ersten Seite können Sie zudem einen Package-Namen angeben. Java verwaltet Klassen in so genannten Packages. Wir werden darauf in Kapitel 3 noch näher eingehen. Einstweilen sollten Sie sich aber schon einmal merken, dass Java erwartet, dass die Datei einer Klasse, die als Teil eines Packages A angelegt wird, auch in einem gleichnamigen Unterverzeichnis A zu finden ist. Sofern Sie den Package-Namen hier im Dialogfeld festlegen, sorgt der JBuilder für die korrekte Einrichtung. Sie sollten danach aber weder den Package-Namen in der Quelldatei noch den Namen des entsprechenden Verzeichnisses auf der Festplatte nachträglich ändern. Auf der zweiten Seite des Anwendungs-Experten können Sie das Hauptfenster der Anwendung konfigurieren. Wir wollen uns damit begnügen, als Titel (ÜBERSCHRIFT) für das Fenster »Hallo« einzutragen. (Deaktivieren Sie die Option zum Zentrieren des Fensters.) Mehr zur Bedeutung der verschiedenen Symbole im Dialogfeld der Objektgalerie erfahren Sie im weiteren Verlauf des Buches, in Kapitel 7 oder durch Drücken des HILFE-Schalters. 5. Klicken Sie auf FERTIG STELLEN. Nach wenigen Sekunden sehen Sie im Projektfenster, dass zwei neue JavaDateien namens Anwendung1.java und Frame1.java hinzugekommen sind. Doppelklicken Sie jeweils auf diese neuen Dateien und werfen Sie einen Blick auf den Inhalt: so sieht Java-Quellcode aus! Ohne JBuilder hätten Sie diese Zeilen selbst erstellen müssen. Schon ziemlich praktisch, so eine Entwicklungsumgebung. Übung 3: Das Programm ausführen Bevor wir das Programm weiter bearbeiten, wollen wir es einmal ausführen lassen. Wenn Sie wollen, können Sie es zur Sicherheit auch vorher speichern (Befehl PROJEKT ... SPEICHERN im Menü DATEI). 6. Rufen Sie im Menü START den Eintrag PROJEKT AUSFÜHREN auf. 35 Kapitel 2 Das erste Programm Für viele Menübefehle gibt es auch ein Symbol zum schnelleren Zugriff; in diesem Fall könnten Sie auch das grüne Dreieck in der Symbolleiste anklicken oder die Funktionstaste Ñ drücken). Wahrscheinlich hören Sie kurz ein Knattern der Festplatte: der JBuilder greift nun auf die Quellcode-Dateien zu und übersetzt sie in den Java-Bytecode. Wenn dabei Fehler auftauchen, werden Sie in einem Meldefenster sowie einer Statusleiste unterhalb des Inhaltsfensters gezeigt. Wenn alles geklappt hat, wird der kompilierte Bytecode nun interpretiert, das heißt in Maschinencode übersetzt und an den Prozessor übergeben. Es sollte auf Ihrem Bildschirm nun ein neues Fenster aufgetaucht sein, das die Titelleiste »Hallo« besitzt. Das ist Ihr erstes ausgeführtes Java-Programm! Abb. 2.3: Unser erstes Programm. Wenn die erste Begeisterung abgeklungen ist, fällt Ihnen sicherlich auf, dass dieses Programm nicht besonders aufregend ist. Es macht nichts und zeigt nichts an. Aber immerhin kann man schon per Maus den Schließknopf betätigen oder es minimieren! 2.2 Quellcode – der erste Kontakt! Bevor es weitergeht und wir das Programm aus dem vorangehenden Abschnitt mit Hilfe der RAD-Programmierung ein wenig ausschmücken wollen, sollten wir es nicht versäumen, einen Blick auf den Quellcode zu werfen, den der JBuilder für uns aufgesetzt hat. Bei diesem Code, aufgeteilt auf die Dateien Anwendung1.java und Frame1.java handelt es sich um das so genannte Anwendungsgerüst, das der JBuilder jedes Mal anlegt, wenn Sie sich im Dialogfeld zu dem Befehl DATEI/NEU für eine Anwendung entscheiden. Es ist allerdings keineswegs 36 Quellcode – der erste Kontakt! das einzige mögliche Anwendungsgerüst. Applets, Servlets und JavaBeans sind beispielsweise Java-Programme und -Bausteine, die über eigene, anders aufgebaute Grundgerüste verfügen. (Das Grundgerüst für Applets werden Sie in Kapitel 14 kennen lernen.) Auch ist das Anwendungsgerüst, das der JBuilder aufsetzt, schon weit ausformuliert und recht komfortabel (insbesondere, wenn Sie im Projekt-Experten irgendwelche Dekorationen für das Hauptfenster ausgewählt haben). Ein minimales Anwendungsgerüst bei gleichzeitigem Verzicht auf eine grafische Oberfläche würde viel einfacher aussehen (siehe Kapitel 3). Nichtsdestotrotz lohnt es, sich mit dem Anwendungsgerüst näher zu befassen, denn Sie werden im Laufe Ihrer Tätigkeit als Java-Programmierer mit dem JBuilder vermutlich unzählige Anwendungen erstellen, die auf diesem Anwendungsgerüst aufbauen. Zudem können wir uns dabei gleich mit einigen grundlegenden Elementen der Java-Syntax vertraut machen. Aber bitte, es geht wirklich nur darum, einen groben Überblick zu gewinnen und einige wichtige Begriffe schon einmal gehört zu haben. Um den Code des Anwendungsgerüst wirklich detailliert erklären zu können, müssten wir Sie mit nahezu allen Konzepten und Elementen von Java auf einmal vertraut machen. Das ist natürlich weder möglich noch sinnvoll. Also lehnen Sie sich entspannt zurück, genießen Sie die nächsten Seiten, versuchen Sie uns zu folgen, soweit es Ihnen möglich ist, und denken Sie daran, dass ab Kapitel 3 alles Wichtige zur Java-Syntax noch einmal ausführlicher erklärt wird. Beginnen wir mit der Datei Anwendung1.java. package erstesprojekt; import javax.swing.UIManager; public class Anwendung1 { boolean packFrame = false; Listing 2.1: Anwendung1.java – 1. Teil des Anwendungsgerüsts //Die Anwendung konstruieren public Anwendung1() { Frame1 frame = new Frame1(); //Frames überprüfen, die voreingestellte Größe haben //Frames packen, die nutzbare bevorzugte //Größeninformationen enthalten, z.B. aus ihrem Layout if (packFrame) { frame.pack(); } else { frame.validate(); } frame.setVisible(true); } 37 Kapitel 2 Das erste Programm //Main-Methode public static void main(String[] args) { try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { e.printStackTrace(); } new Anwendung1(); } } Das sieht ja alles ziemlich kryptisch aus, aber lassen Sie sich nicht entmutigen. Wir greifen nur einige wichtige Elemente heraus. Fangen wir mit der folgenden Zeile an: public class Anwendung1 { Hiermit wird eine Klasse namens Anwendung1 definiert. Aber was um Himmels willen ist eine Klasse? Das ist gar nicht so einfach zu erklären. Klassen und Objekte Klassen sind im Grunde Beschreibungen von Dingen, mit denen ein Programm arbeiten möchte. Man kann sich das in etwa wie beim Zinnfigurengießen vorstellen. Nehmen wir an Sie wollen irgendeine historische Schlacht nachstellen. Das Erste, was Sie machen, ist sich für die beteiligten Figuren (Soldaten und Offiziere der beteiligten Länder, Kanonen, Pferde, etc.) Gussformen zu kaufen. Danach gehen Sie daran, die Figuren zu gießen, zu bemalen und aufzustellen. Ranghohe Offiziere werden Sie nur wenige Male gießen, einfache Soldaten oder Reiter werden sie öfters gießen. Übertragen auf ein Java-Programm entsprechen die Gussformen den Klassen. Wenn Sie ein Programm schreiben würden, das die betreffende Schlacht simuliert, würden Sie für die beteiligten Figuren keine Gussformen erwerben, sondern Klassen definieren. Und statt aus den Gussformen die eigentlichen Figuren zu gießen, erzeugen Sie in Ihrem Programm die Figuren als Objekte der Klassen – einen Vorgang, den man auch als Instanzbildung bezeichnet. Klassen für die ranghöheren Offiziere werden Sie nur wenige Male instantiieren, während Sie auf der Grundlage der Klassen für Soldaten, Pferde oder Kanonen sicherlich mehrere Objekte erzeugen werden. 38 Quellcode – der erste Kontakt! Wie die Figuren, die aus einer Form gegossen werden, sind auch die Objekte einer Klasse alle gleich. Die Objekte der Klasse Major sind alles Majore, die Objekte der Klasse Soldat sind alles Soldaten. Die einzelnen Objekte einer Klasse können aber durchaus individuelle Züge aufweisen. Nehmen wir die einfachen Soldaten. Die gegossenen Zinnsoldaten können Sie beispielsweise bemalen, um so den einzelnen Soldatenfiguren Individualität zu verleihen (wobei die Figur immer noch ein Soldat, sprich ein Guss der Form Soldat, bleibt). Die Objekte der Klasse Soldat kann man natürlich nicht bemalen, aber sie verfügen über bestimmte Eigenschaften, die in der Klasse definiert sind (beispielsweise Name, Alter, Haarfarbe). Diesen Eigenschaften kann man individuelle Werte zuweisen. Zum Abschluss dieses Diskurs müssen wir uns von dem Zinnsoldatenbeispiel lösen. Java ist vollständig objektorientiert, was bedeutet, dass der gesamte Code in Klassen verpackt ist. Dadurch folgt zwangsläufig, dass diese Klassen nicht immer für so anschauliche Dinge wie Zinnsoldaten stehen. Klassen können auch programmtechnische Dinge beschreiben, wie zum Beispiel die Anwendung selbst oder das Hauptfenster der Klasse. Ja, sie können sogar einfach als Sammlung von mehr oder weniger zusammengehörenden Eigenschaften und Methoden fungieren, ohne dass diese Eigenschaften und Methoden ein irgendwie geartetes reales Objekt beschreiben würden (was aber selten guter Programmierstil ist). Zurück zu unserem Code. Die obige Zeile zeigt also an, dass ab dieser Stelle die Definition einer Klasse mit Namen Anwendung1 folgt. Die Definition dieser Klasse – das heißt alles, was zu dieser Klasse gehören soll – folgt nun eingeschlossen in geschweiften Klammern. Übrigens ist es ganz egal, wo die Klammern nun genau stehen. Die öffnende Klammer kann zum Beispiel auch in der nächsten Zeile stehen. Sie können aber auch die gesamte Klassendefinition hintereinander in eine Zeile schreiben! Es wäre nur höchst unübersichtlich. Aber weiter mit dem Quellcode. Zunächst erscheint nach der öffnenden geschweiften Klammer: boolean packFrame = false; Damit wird eine so genannte Variable definiert. 39 Kapitel 2 Das erste Programm Variablen Programme dienen der Verarbeitung von Daten. Dazu ist es erforderlich, dass das Programm Daten zwischenspeichern kann. Dies geschieht im Arbeitspeicher des Rechners. Da es aber recht unhandlich wäre, im Programm mit echten Speicheradressen zu arbeiten (lege den Wert 3 in Speicheradresse 0xFFFF12A4 ab, addiere die Werte aus den Speicheradressen 0xF1FEE83B5 und 0xF1FEE83CC), erlaubt uns Java die Einrichtung von Synonymen für Speicheradressen – die so genannten Variablen. Wenn Sie eine Variable definieren, reserviert der Compiler für diese Variable Speicher im Arbeitsspeicher des Computers und verbindet den Variablennamen mit diesem Speicher. Um Arbeitsspeicher reservieren zu können, muss der Java-Compiler allerdings wissen, wie viel Speicher für die Werte, die der Variablen zugewiesen werden können, benötigt wird. Daher muss man bei der Variablendefinition einen Datentyp angeben. Der Datentyp legt fest, welche Art von Daten der Variablen zugewiesen werden können (beispielsweise Ganzzahlen, Bruchzahlen oder Zeichen) und wie viel Speicherplatz für die Variable reserviert wird (für Ganzzahlen werden beispielsweise 4 Byte reserviert). Einer Variablen, die für Ganzzahlen definiert wurde, kann man nur Ganzzahlen (14, 2345, -3) zuweisen. Zudem kann Sie immer nur einen Wert zur Zeit enthalten und dieser Wert muss innerhalb eines bestimmten Wertebereichs liegen (das heißt, die Werte können nicht beliebig groß werden, da sie sonst mehr Speicher belegen würden, als für die Variable reserviert wurde). Die oben deklarierte Variable heißt packFrame und ist vom Datentyp boolean (steht für Wahrheitswerte: true (wahr) und false (falsch)). Ferner wird durch das Gleichheitszeichen ein Wert an packFrame zugewiesen (der Wert false). Ein weiterer wichtiger Bestandteil dieser Zeile ist das unscheinbare Semikolon am Ende: es zeigt an, dass die Variablendefinition hier endet und darf nicht weggelassen werden. Der Compiler braucht dieses Zeichen als Hilfsmittel beim Übersetzen des Quellcodes in Bytecode. Gehen wir nun weiter zu den nächsten zwei Zeilen. //Die Anwendung konstruieren public Anwendung1() { Die obere Zeile beginnt mit zwei Schrägstrichen. Dies ist das Kommentarzeichen. Jede Zeile, die so beginnt, wird vom Compiler ignoriert. Kommen- 40 Quellcode – der erste Kontakt! tarzeilen dienen nur zur Information für den Programmierer; er kann so im Quellcode notieren, was an dieser Stelle gemacht werden soll. In der nächsten Zeile haben wir wieder eine Definition und zwar eine Methodendefinition. Das erkennt man an dem Klammerpaar () nach dem Namen der Methode. Ähnlich wie bei der Klassendefinition folgt nun ein Paar von geschweiften Klammern. Alles, was dazwischen steht, gehört zu der Methode Anwendung1 und bildet den so genannten Methodenrumpf. Methoden Eine Methode ist eine Sammlung von Anweisungen, von Befehlen, die eine bestimmte Aufgabe erledigen – beispielsweise einen Sinuswert berechnen, den Mittelwert eine Reihe von Zahlen bestimmen, eine Kurve oder eine Figur zeichnen, was auch immer. Beachten Sie, dass hier in den Methodendefinitionen festgelegt wird, was das Programm eigentlich macht. Java-Quellcode besteht aus einer Vielzahl von Definitionen (Klassendefinitionen, Variablendefinitionen, Methodendefinitionen etc.). Diese Definitionen richten sich an den Compiler und teilen ihm mit, aus welchen Elementen ein Programm aufgebaut ist: ✘ Hier ist die Definition einer Klasse namens Anwendung1, von der ich später Objekte erzeugen möchte. ✘ Reserviere mir Speicher für eine boolean-Variable namens packFrame. ✘ Hier ist die Definition einer Methode Anwendung1, die ich später irgendwann ausführen möchte. Das Besondere der Methodendefinitionen ist, dass sie den eigentlichen ausführbaren Code enthalten. Ist eine Methode erst einmal definiert, kann sie im Programm aufgerufen werden. Wird sie aufgerufen, führt der Compiler die Anweisungen aus dem Rumpf der Methodendefinition aus. Methoden können nur als Teil von Klassen definiert werden. In manchen Programmiersprachen gibt es neben oder statt Methoden so genannte Funktionen. Funktionen enthalten wie Methoden ausführbaren Code zur Lösung einer bestimmten Aufgabe, sind aber nicht als Teil einer Klasse definiert. Wenn Sie von einer Programmiersprache wie Pascal oder Visual Basic kommen und noch nicht mit objektorientierter Programmierung zu tun hatten, merken Sie sich einfach, dass eine Methode eine Funktion (oder Prozedur) ist, die als Teil einer Klasse definiert ist. 41 Kapitel 2 Das erste Programm Warum aber heißt die Methode Anwendung1 genauso wie die Klasse, in der sie definiert ist? Dies liegt daran, dass es sich um eine spezielle Art von Methode handelt: einer so genannten Konstruktormethode (oder einfach einem Konstruktor). Der Konstruktor einer Klasse wird automatisch aufgerufen, wenn ein Objekt der Klasse erzeugt wird. In unserem Anwendungsgerüst ist dies ganz am Ende des Listings der Fall: ... } new Anwendung1(); } } Hier wird ein Objekt der Klasse Anwendung1 erzeugt, wozu der Compiler den Konstruktor der Klasse Anwendung1 aufruft. Gehen wir nun weiter zur nächsten Methode: //Main-Methode public static void main(String[] args) { Sie sehen, dass die Definition dieser Methode namens main() etwas anders aussieht als die vorige, zum Beispiel stehen noch zusätzliche Angaben in dem runden Klammernpaar. Sie besagen, dass die Methode beim Aufruf einen Parameter erwartet. Aber davon lassen Sie sich mal nicht verwirren. Wie bei Anwendung1() folgt in geschweiften Klammern eingeschlossen der Rumpf der Methode. Wie schon gesagt, sind Methoden die Stellen, wo in einem Java-Programm wirklich etwas passiert, wo richtige Befehle ausgeführt werden. Alles andere (wie zum Beispiel Variablendefinitionen) dient nur dazu, die Daten zu beschreiben, mit denen die Methoden arbeiten sollen. Jedes Java-Programm braucht dabei mindestens eine Methode, mit der die Abarbeitung des Programms durch den Computer beginnen muss. Schließlich muss er ja wissen, wo es losgehen soll. Und diese Methode muss den Namen main() haben und auch exakt wie oben mit public static void main(String[] args) beginnen. Die main()-Methode Warum so kompliziert, warum den Beginn des Programms in einer Methode einer Klasse verstecken? In semi-professionellen Sprachen wie Basic schrieb man früher seine Programme einfach als eine Folge von Anweisungen. Der Interpreter begann die Ausführung des Programms mit der ersten Anweisung im Quelltext und arbeitete sich dann nach unten durch. 42 Quellcode – der erste Kontakt! Zum Aufsetzen größerer Programme ist dieses Verfahren aber gänzlich ungeeignet. Professionelle Programmiersprachen halten ihre Programmierer daher üblicherweise an, den Quelltext zu strukturieren. In C sah (und sieht) dies beispielsweise so aus, dass Anweisungen nicht beliebig im Quellcode stehen dürfen, sondern in Funktionen eingefasst werden müssen. So wird der Programmierer angehalten, Teilprobleme zu identifizieren und diese durch die Implementierung von Funktionen zu lösen. Statt eines endlosen Flusses von Anweisungen besteht ein solches Programm aus einer Reihe von aufeinanderfolgenden Funktionsdefinitionen. Wo aber beginnt die Ausführung eines solchen Programms? Für C hat man sich darauf geeinigt, dass jedes Programm eine Funktion namens main() enthalten soll. Das Programm beginnt mit der Ausführung dieser Funktion und der Programmierer kann aus dieser Funktion heraus, die anderen Funktionen, die er aufgesetzt hat, aufrufen. Später wurde C um objektorientierte Konzepte zu C++ erweitert, behielt aber das Konzept der Funktionen und der main()-Funktion bei. Java ist in vielen Punkten C++ recht ähnlich. Daher beginnen Java-Anwendungen ebenfalls mit Ausführung der main()-Funktion. Da es aber in Java keine Funktionen, sondern nur Methoden gibt, muss main() in Java-Anwendungen als Methode einer Klasse definiert werden. Dies führt aber gleich zu einem weiteren Problem. Auf die Variablen und Methoden einer Klasse kann man an sich nur über ein Objekt der Klasse zugreifen. Um ein Objekt der Klasse mit der main()-Funktion zu erzeugen, muss das Programm aber schon ausgeführt werden, sprich main() muss bereits aufgerufen worden sein. Hier beißt sich die Schlange in den Schwanz. Die Lösung zu diesem Dilemma ist die Definition der Methode als static. Die staticDefinition teilt dem Compiler mit, dass diese Methode auch ohne Objekt der Klasse aufgerufen werden kann. So, nun haben Sie aber schon viel gelernt. Fassen wir zusammen: In der Datei Anwendung1.java wird eine Klasse Anwendung1 definiert, die eine Variable packFrame und zwei Methoden – Anwendung1() und main() – besitzt. Werfen wir nun einen kurzen Blick in die andere Quelldatei: Frame1.java. package erstesprojekt; import java.awt.*; import java.awt.event.*; import javax.swing.*; Listing 2.2: Frame1.java – 2. Teil des Anwendungsgerüsts public class Frame1 extends JFrame { JPanel contentPane; 43 Kapitel 2 Das erste Programm BorderLayout borderLayout1 = new BorderLayout(); public Frame1() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); try { jbInit(); } catch(Exception e) { e.printStackTrace(); } } private void jbInit() throws Exception { contentPane = (JPanel) this.getContentPane(); contentPane.setLayout(borderLayout1); this.setSize(new Dimension(400, 300)); this.setTitle("Hallo"); } protected void processWindowEvent(WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } } } Beginnen wir mit der Zeile: public class Frame1 extends JFrame { Sie wissen nun schon, dass hier eine weitere Klasse namens Frame1 definiert wird. Die extends Angabe zeigt an, dass diese neue Klasse Frame1 eine schon bestehende Klasse namens JFrame erweitert. Alles, was JFrame an Variablen und Methoden besitzt, hat nun auch die Klasse Frame1. Diese Klasse erzeugt das Hauptfenster unserer Anwendung. Schauen Sie sich die Methode jbInit() an. Dort finden Sie im Rumpf der Methode die folgende Anweisung: this.setTitle("Hallo"); Hier sehen Sie, wie eine Methode benutzt, das heißt aufgerufen, wird: Man gibt den Namen der Methode an, gefolgt von dem typischen Paar runder Klammern und – nie vergessen! – dem Semikolon. Der Zusatz this. vor dem Methodennamen besagt, dass der Compiler die Definition der Methode in der Klasse suchen soll, in der dieser (this!) Aufruf steht, also hier die Klasse Frame1. 44 Programmieren in der RAD-Umgebung Die Methode setTitle()erwartet einen Parameter, nämlich einen kurzen Text, der in der Titelleiste des Fensters gezeigt werden soll. So einen Text nennt man Zeichenkette oder auf Englisch String. Ein String beginnt und endet immer mit dem Hochzeichen ". Probieren Sie doch mal, der Methode setTitle() einen anderen String als Parameter mitzugeben (z.B. "Meine erste Anwendung") und führen Sie dann das Programm neu aus. 2.3 Programmieren in der RAD-Umgebung Rekapitulieren wir kurz was bisher geschehen ist. Wir haben ein neues Projekt angelegt und den JBuilder aufgefordert, das Projekt um das Codegerüst für eine Anwendung zu erweitern. Der JBuilder hat darauf zwei neue Quellcodedateien in das Projekt aufgenommen (Anwendung1.java und Frame1.java) und den Code des Anwendungsgerüsts auf diese beiden Quelldateien aufgeteilt. Mit Hilfe des Menübefehls START/PROJEKT AUSFÜHREN konnten wir das Anwendungsgerüst kompilieren und ausführen. Ohne selbst eine einzige Zeile Java-Code aufzusetzen, haben wir also bereits ein vollwertiges Programm mit grafischer Benutzeroberfläche erzeugt! Einziger Wermutstropfen ist, dass das Programm nicht gerade geeignet ist, Freunde und Bekannte zu beeindrucken. Außer einem leeren Fenster, das man minimieren und schließen kann, hat es kaum etwas zu bieten (siehe Abbildung 2.3). Dies wollen wir in diesem Abschnitt ändern und uns dabei gleichzeitig mit den typischen Arbeitsabläufen bei der komponentengestützten Programmierung vertraut machen. Die RAD-Umgebung aktivieren Als Erstes wollen wir im Fenster den Text »Hallo Welt« ausgeben. Eine Möglichkeit dies zu tun, wäre den Text in das Fenster zu zeichnen (siehe Kapitel 10.1 und 11.3). Einfacher und in vielen Fällen sinnvoller ist es, ein spezielles Steuerelement – ein Label oder statisches Textfeld – in das Fenster aufzunehmen. Wechseln wir also erst einmal in die RAD-Umgebung. 1. Wählen Sie im Projektfenster (durch Doppelklick) die Frame1.java-Datei aus. 2. Klicken Sie dann im Inhaltsfenster unten auf das Register DESIGN. Es erscheint die RAD-Umgebung. 45 Kapitel 2 Das erste Programm Abb. 2.4: Das Hauptfenster der Anwendung im UI-Designer Strukturfenster Komponentenpalette UI-Designer (mit Hauptfenster) Inspektor Das Inhaltsfenster ist nun dreigeteilt. ✘ Am oberen Rand des UI-Designers (des Inhaltsfensters) sehen Sie die Komponentenpalette, in der – auf mehrere Register verteilt – die zur Verfügung stehenden Komponenten aufgelistet sind. (Grämen Sie sich nicht, wenn Ihre Komponentenpalette über weniger Register verfügt. Wir haben für das Buch die Enterprise-Edition verwendet und diese ist halt bezüglich der mitgelieferten Komponenten etwas üppiger ausgestattet als die Personal- oder die Professional-Edition.) ✘ Darunter sehen Sie links eine leere, graue Fläche. Dies ist das Hauptfenster unserer Anwendung. Wenn das Fenster zu groß ist, um im UIDesigner vollständig angezeigt werden zu können, stellt Ihnen der JBuilder Bildlaufleisten zum Scrollen zur Verfügung. Besser ist es allerdings das JBuilder-Fenster zu vergrößern oder die umliegenden Fensterbereiche zu verkleinern. Schließlich können Sie das Hauptfenster der Anwendung auch, wie wir es getan haben, ein wenig verkleinern, indem Sie rechts unten die schwarzen Markierungspunkte des Fensters verschieben (links im Strukturfenster sollte der Knoten this ausgewählt sein). Beachten Sie aber, dass alle Änderungen im UI-Designer direkt das betreffende Fenster betreffen. Wenn Sie also die Größe des Fensters ändern, verkleinern Sie nicht etwa nur die Darstellung des Fensters im UI-Designer. Sie ändern tatsächlich die Größe des Fensters. 46 Programmieren in der RAD-Umgebung ✘ Rechts im Inhaltsfenster sehen Sie den Inspektor, in dem Sie die Eigenschaften (und Ereignisse) für die im Designer (bzw. im Strukturfenster) markierten Elemente bearbeiten können. Ganz links, unter dem Projektfenster, ist das Strukturfenster mit dem Komponentenbaum hinzugekommen. In diesem werden die Komponenten aufgeführt, die Sie in Ihrem Programm verwenden. Im Abschnitt UI (für User Interface = Benutzeroberfläche) sehen Sie als obersten Knoten this. Dieser Knoten repräsentiert das Fenster. Darunter befindet sich ein untergeordneter Knoten mit der Bezeichnung contentPane. Die contentPane bezeichnet den Bereich des Fensters, in den man zeichnen oder in den man Komponenten einfügen kann. Weiterhin sehen Sie in der Strukturansicht, dass die contentPane über ein Layout, genau gesagt ein BorderLayout, verfügt. Layouts sorgen für die automatische Ausrichtung untergeordneter Komponenten in einer übergeordneten Container-Komponente (in diesem Falle die contentPane). Dies kann für Anwendungen, die auf unterschiedlichen Plattformen (Windows, Mac, Linux, etc.) laufen sollen, ein großer Vorteil sein. Für uns sind die Layouts aber im Moment uninteressant, ja sogar störend, da wir unsere Komponenten lieber selbst ausrichten würden. Wir deaktivieren also das Layout. 3. Klicken Sie im Strukturfenster auf den Knoten contentPane. Im Inspektor werden jetzt die Eigenschaften der contentPane angezeigt. 4. Klicken Sie in das Eingabefeld rechts neben der Eigenschaft Layout. Wählen Sie in der aufspringenden Liste den Eintrag null aus. Komponenten aufnehmen Jetzt können wir eine Label-Komponente in das Fenster aufnehmen. 5. Klicken Sie in der Komponentenpalette auf das Register SWING. 6. Suchen Sie nach der Komponente JLabel (wenn Sie den Mauszeiger etwas länger über einer Komponente stehen lassen, wird als ToolTip, ein kleiner Hilfetext, der Name der Komponentenklasse angezeigt). Klicken Sie auf das Symbol der Komponente. 7. Klicken Sie nun in die leere Fläche des Fensters. Der JBuilder fügt eine Instanz der Komponente in das Fenster ein. 8. Speichern Sie nun das Projekt (Befehl ALLES SPEICHERN im Menü DATEI) und führen Sie das Programm erneut aus (Taste Ñ). 47 Kapitel 2 Das erste Programm Abb. 2.5: Das Fenster mit einem Label-Feld Bevor wir das eingefügte Label-Feld weiter anpassen, wollen wir analysieren, was eigentlich geschehen ist. Nachdem wir das Label-Feld in das Fenster aufgenommen hatten, wurde es sofort im UI-Designer angezeigt. Aber auch der Komponentenbaum im Strukturfenster wurde aktualisiert und um einen Eintrag jLabel1 unter dem contentPane-Knoten erweitert. Noch mehr erfahren wir, wenn wir aus der DESIGN-Ansicht zur QUELLEN-Ansicht wechseln. Klicken Sie also unter dem UI-Designer auf das Register QUELLE und scrollen Sie im Inhaltsfenster an den Anfang der Datei zur Definition der Klasse Frame1. package erstesprojekt; import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Frame1 extends JFrame { JPanel contentPane; JLabel jLabel1 = new JLabel(); Neu hinzugekommen ist hier die letzte Zeile, in der zwei Dinge passieren. ✘ Als Element der Klasse Frame1 wird eine Variable namens jLabel1 vom Typ JLabel definiert. JLabel jLabel1 ✘ Zweitens wird ein Objekt der Klasse JLabel erzeugt und der Variablen jLabel1 zugewiesen. jLabel1 = new JLabel(); Der Grund hierfür ist folgender: Hinter den Komponenten aus der Komponentenpalette stehen Klassen (beispielsweise JLabel für Label-Felder). Wenn wir eine Komponente aus der Palette auswählen und per Mausklick in ein Fenster einfügen, erzeugt der JBuilder ein Objekt dieser Klasse (new JLabel). Damit wir jederzeit auf dieses Objekt zugreifen können, richtet der JBuilder weiterhin eine Variable vom Typ des Objekts ein (JLabel jLabel1) und verbindet diese Variable mit dem gerade erzeugten Objekt. 48 Programmieren in der RAD-Umgebung Scrollen Sie ein wenig nach unten zur Methode jbInit(): private void jbInit() throws Exception { jLabel1.setText("jLabel1"); jLabel1.setBounds(new Rectangle(86, 59, 41, 17)); ... contentPane.add(jLabel1, null); } Über den Variablennamen jLabel1 wird auf zwei Methoden der Klasse JLabel zugegriffen. Die Methode setText() dient dazu den Text im LabelFeld festzulegen, die Methode setBounds() bestimmt die Abmaße des Label-Felds. Die letzte Anweisung contentPane.add(jLabel1, null); fügt das Label-Feld als untergeordnete Komponente in die contentPane ein. Welche Methoden zur Programmierung mit einer Komponente zur Verfügung stehen, kann man in der Online-Hilfe nachschlagen. Komponenten konfigurieren Wechseln Sie jetzt noch einmal zurück in die DESIGN-Ansicht. 9. Markieren Sie das Label-Feld. Sie können dazu entweder das Label-Feld im UI-Designer oder den zugehörigen Knoten (jLabel1) im Strukturfenster anklicken. Im Inspektor auf der rechten Seite werden daraufhin die Eigenschaften des Label-Felds angezeigt. Abb. 2.6: Bearbeiten der Eigenschaften einer Komponente 49 Kapitel 2 Das erste Programm 10. Ändern Sie den Text des Label-Felds. Klicken Sie dazu in das Eingabefeld rechts neben der Eigenschaft text und geben Sie als neuen Text »Hallo Welt!« ein. 11. Ändern Sie den Font des Label-Felds. Klicken Sie in das Eingabefeld rechts neben der Eigenschaft font. Es erscheint eine Schaltfläche mit einer Ellipse (...), die Sie anklicken. In dem aufspringenden Dialogfenster setzen Sie die Größe der Schriftart auf 24. Der Text kann jetzt nicht mehr vollständig in dem Label-Feld angezeigt werden. Wir müssen es also vergrößern. 12. Klicken Sie mit der linken Maustaste auf einen der Punkte des Markierungsrahmens des Label-Felds und ziehen Sie den Rahmen auf. Schön wäre es auch, wenn der Schriftzug horizontal zentriert im Fenster erscheinen würde. 13. Rücken Sie das Label-Feld ins obere Drittel des Fensters. Sie brauchen dazu nur mit der linken Maustaste auf das Label-Feld zu klicken und es mit gedrückt gehaltener Maustaste zu verschieben. 14. Um das Label-Feld horizontal im Fenster zu zentrieren, klicken Sie mit der rechten Maustaste auf das Label-Feld und wählen den Befehl ZENTRIERT aus. 15. Um den Schriftzug im Label-Feld horizontal zu zentrieren, klicken Sie im Inspektor rechts neben die Eigenschaft horizontalAlignment und wählen Sie die Option Center aus. Fenster sind auch Komponenten Aus Sicht der RAD-Umgebung des JBuilders sind Fenster ebenfalls Komponenten, die im Inspektor bearbeitet werden können. Wir wollen dies nutzen, um den Titel unseres Fensters zu ändern und das Fenster selbst etwas poppiger erscheinen zu lassen. 16. Wählen Sie das Fenster aus. Da wir das Fenster nicht im UI-Designer markieren können (es wird vollständig von der contentPane verdeckt), markieren wir es im Komponentenbaum des Strukturfensters (Knoten this). 17. Klicken Sie im Inspektor in das Eingabefeld neben der Eigenschaft title und geben Sie als neuen Titel »Meine erste Anwendung ein«. 18. Ändern Sie die Hintergrundfarbe. Klicken Sie in das Feld neben der Eigenschaft background und wählen Sie als neue Farbe Rosa. Sollte Ihnen diese Farbe nicht zusagen, wählen Sie eine andere oder klicken Sie 50 Programmieren in der RAD-Umgebung auf die Schaltfläche mit der Ellipse und mischen Sie sich Ihre eigene Farbe zusammen. 19. Speichern Sie das Projekt (Befehl ALLES SPEICHERN im Menü DATEI) und führen Sie das Programm erneut aus (Taste Ñ). Abb. 2.7: Schade, das wunderbare Pink ist durch die Konvertierung in Graustufen verloren gegangen. Ereignisse bearbeiten Komponenten verfügen nicht nur über Eigenschaften, sondern auch über Ereignisse. Die Ereignisse der Label-Komponente sind allerdings ziemlich uninteressant für uns. Wir erweitern unsere Anwendung daher um eine Schaltfläche und fangen das Drücken der Schaltfläche ab. 20. Fügen Sie unter dem Label-Feld eine Schaltfläche ein. Wählen Sie die JButton-Komponente aus dem SWING-Register der Komponentenpalette. 21. Ändern Sie den Titel der Schaltfläche (Eigenschaft text) in »Klick mich« und zentrieren Sie die Schaltfläche horizontal. Jetzt wollen wir festlegen, was geschehen soll, wenn der Anwender die Schaltfläche drückt. 22. Klicken Sie am unteren Rand des Inspektors auf das Register EREIGNISSE. Es erscheint eine Liste von verschiedenen Ereignissen, die man bearbeiten kann. (Achten Sie darauf, dass die Schaltfläche markiert ist, damit Sie auch tatsächlich die Ereignisse des Schalters angezeigt bekommen.) Von diesen Ereignissen interessiert uns im Moment nur actionPerformed, da dieses Ereignis ausgelöst wird, wenn der Anwender auf die Schaltfläche klickt. 51 Kapitel 2 Das erste Programm Wenn Sie sich näher über ein Ereignis informieren wollen, markieren Sie im Inspektor das Ereignis und drücken Sie É. 23. Doppelklicken Sie in das Eingabefeld neben dem actionPerformedEreignis. Der JBuilder legt daraufhin eine neue Methodendefinition an und wechselt in die QUELLEN-Ansicht, wo Sie die Methode direkt bearbeiten können. void jButton1_actionPerformed(ActionEvent e) { } Gleichzeitig setzt er Code auf, der dafür sorgt, dass beim Anklicken der Schaltfläche automatisch die betreffende Methode aufgerufen und ausgeführt wird. Dieser Code soll uns aber im Moment nicht weiter interessieren, da für uns keine Notwendigkeit besteht, diesen Code zu verändern. Was wir aber tun wollen, ist die Methode zu implementieren, die beim Drücken des Schalters aufgerufen wird. Also Achtung! Gleich schreiben wir unsere erste Zeile eigenen Java-Code! Eigenschaften zur Laufzeit ändern Der JBuilder hat uns bereits zur Definition der Ereignisbehandlungsmethode geführt. void jButton1_actionPerformed(ActionEvent e) { } Wir müssen jetzt nur noch zwischen die geschweiften Klammern die Anweisungen einfügen, die abgearbeitet werden sollen, wenn das Ereignis eintritt. Doch was sollen wir hineinschreiben? Wir haben uns doch noch gar nicht näher mit Java und der Java-Syntax beschäftigt? Nun, das ist auch gar nicht unbedingt notwendig. Wir begnügen uns einfach mit der Veränderung von Komponenten zur Laufzeit und schauen uns die benötigten Techniken beim JBuilder ab. Was macht der JBuilder, wenn wir den Text des Label-Felds im Inspektor ändern? Richtig, er erzeugt im Quelltext einen entsprechenden Methodenaufruf. Das können wir auch. 24. Implementieren Sie die Ereignisbehandlungsmethode. 52 Programmieren in der RAD-Umgebung Zuerst müssen wir auf das Objekt zugreifen, das wir bearbeiten wollen. Dies geschieht über den Variablennamen, den der JBuilder für das Objekt definiert hat. Im Falle unseres Label-Felds wäre dies also jLabel1. void jButton1_actionPerformed(ActionEvent e) { jLabel1 An den Namen hängen wir einen Punkt an. Für den Java-Compiler heißt dies, dass wir auf eine Eigenschaft oder eine Methode des Objekts zugreifen wollen. void jButton1_actionPerformed(ActionEvent e) { jLabel1. Der JBuilder springt uns jetzt zur Hilfe. Er weiß, dass es sich bei jLabel1 um ein Objekt der Klasse JLabel handelt und zeigt uns eine Liste der Methoden dieser Klasse an. Abb. 2.8: Code-Insight im JBuilderEditor Aber wie findet man aus dem Wust der angebotenen Methoden, die Methode zum Ändern des Titels des Label-Felds. Ganz einfach: Die Methoden zum Abfragen und Setzen von Komponenteneigenschaften lauten meist genauso wie die Eigenschaften im Inspektor. Methoden, die den Wert einer Eigenschaft abfragen, ist das Präfix get vorangestellt, Methoden, die den Wert einer Eigenschaft ändern, beginnen mit set. Danach folgt der Name der Eigenschaft mit großen Anfangsbuchstaben. Es ist daher anzunehmen, dass die Methode zum Setzen des Titels (Eigenschaft text) setText() heißt. Richtig, es findet sich in der Liste auch eine entsprechende Methode. 53 Kapitel 2 Das erste Programm Wenn Sie den betreffenden Eintrag in der Liste doppelt anklicken, fügt der JBuilder den Methodenaufruf ein. Müssen Sie der Methode Argumente übergeben, werden Sie vom JBuilder darauf hingewiesen. Die Methode setText() erwartet beispielsweise, dass Sie in den runden Klammern des Methodenaufrufs den neuen Titel als String (Text in doppelten Anführungszeichen) angeben: void jButton1_actionPerformed(ActionEvent e) { jLabel1.setText("Auf Wiedersehen!"); } 25. Speichern Sie das Projekt (Befehl ALLES SPEICHERN im Menü DATEI) und führen Sie das Programm erneut aus (Taste Ñ). Abb. 2.9: Das Programm nach Drücken des Schalters Sollte der Text »Auf Wiedersehen!« nicht vollständig angezeigt werden, liegt dies daran, dass Ihr Label-Feld zu klein ist. Vergrößern Sie es einfach durch Aufziehen des Markierungsrahmens im Inspektor und zentrieren Sie es danach noch einmal. Die Eigenschaft name Wie Sie bereits wissen, erzeugt der JBuilder für jede Komponente, die Sie aus der Komponentenpalette in Ihre Anwendung einfügen, eine passende Variable. Der Name dieser Variablen kann über die Eigenschaft name im Inspektor geändert werden. Der JBuilder ersetzt dann im Quelltext der aktuellen Datei alle Vorkommen des alten Namens durch den neuen Namen. Um Fehler bei der Ersetzung zu vermeiden (etwa, wenn die Variable auch noch in anderen Quelldateien verwendet wird), empfiehlt es sich, die Namen der eingefügten Komponenten möglichst gleich nach dem Einfügen zu ändern. 54 Was tut sich auf der Festplatte? Soweit es die Beispiele in diesem Buch betrifft, werden wir aber meist die vom JBuilder vergebenen Standardnamen beibehalten. Damit wollen wir den ersten Kontakt mit Java und dem JBuilder beenden. Sie haben nun hoffentlich schon eine erste, wenn auch vielleicht noch etwas vage Vorstellung, wie so ein Java-Programm aussieht und wie der JBuilder Ihnen bei der Arbeit hilft. 2.4 Was tut sich auf der Festplatte? Zum Abschluss dieses Kapitels wollen wir uns noch anschauen, wie sich das von uns erzeugte Projekt auf der Festplatte präsentiert. Erinnern Sie sich an Schritt 1 aus Abschnitt 2.1? Dort wurden Sie aufgefordert einen Pfad und ein übergeordnetes Projektverzeichnis anzugeben. Suchen Sie jetzt nach diesem Verzeichnis auf Ihrer Festplatte. In diesem Verzeichnis hat der JBuilder ✘ Die Projektdatei (mit der Extension .jpr) und die HTML-Beschreibungsdatei abgelegt und ✘ Unterverzeichnisse für die Quelldateien (src) sowie die kompilierten class-Dateien (classes) angelegt. (Der Compiler speichert den für eine .java-Datei erzeugten Bytecode in einer .class-Datei.) Wenn Sie in das Unterverzeichnis src (für die Quellcodedateien) hinabsteigen, finden Sie in diesem ein weiteres Unterverzeichnis. Dieses Verzeichnis trägt den Namen des Packages, in dem die Klassen Ihres Anwendungsgerüst definiert sind (siehe erste Zeile der Quelldateien und Schritt 4 aus Abschnitt 2.1). Im Package-Verzeichnis schließlich finden Sie die Quelldateien Ihres Projekts. Abb. 2.10: Java-Projekte auf der Festplatte 55 Kapitel 2 2.5 Das erste Programm Anwendungen von außerhalb des JBuilder aufrufen Natürlich wäre der Wert Ihrer Java-Anwendungen recht beschränkt, wenn man zur Ausführung der Programme stets zuerst den JBuilder starten müsste. Nun, der JBuilder ist selbstverständlich nicht erforderlich, es reicht, wenn auf dem System, auf dem die Programme ausgeführt werden, ein Java-Interpreter vorhanden ist. Anwendungen unter Windows starten Eine Möglichkeit, eine einmal erstellte Java-Anwendung unter Windows auszuführen, besteht darin, den Java-Interpreter über die MSDOS-Eingabeaufforderung aufzurufen. 1. Öffnen Sie ein MSDOS-Eingabeaufforderungsfenster, indem Sie im Windows-Startmenü den Befehl PROGRAMME/MSDOS-EINGABEAUFFORDERUNG auswählen (je nach Windows-Version auch PROGRAMME/EINGABEAUFFORDERUNG oder PROGRAMME/ZUBEHÖR/EINGABEAUFFORDERUNG). 2. Im MSDOS-Eingabeaufforderungsfenster wechseln Sie in das Verzeichnis, in dem die Hauptklasse der Anwendung oder – falls die Hauptklasse wie in unserem Falle in einem Package liegt – das Package-Unterverzeichnis steht. (In Anlehnung an unser erstes Beispielprogramm und Abbildung 2.10 wäre dies das Verzeichnis C:\JBProjekte\ErstesProjekt\classes.) 3. Rufen Sie den Java-Compiler auf (falls Sie das JDK-BIN-Verzeichnis, das zusammen mit dem JBuilder angelegt wurde, nicht in den Pfad aus Ihrer autoexec.bat eingetragen haben, müssen Sie den kompletten Pfad zum java.exe-Interpreter angeben.) und geben Sie dem Java-Interpreter beim Aufruf den Namen der Hauptklasse an. Die Hauptklasse ist die Klasse, in der die main()-Methode definiert ist. Liegt die Hauptklasse in einem Package, stellen Sie dem Klassennamen den Package-Namen und einen Punkt voran. 56 Anwendungen von außerhalb des JBuilder aufrufen Abb. 2.11: Aufruf aus der MSDOS-Eingabeaufforderung Bequemer ist es allerdings, wenn Sie eine Batch-Datei für den Aufruf des Programms schreiben. 1. Öffnen Sie den Notepad-Editor (Befehl START/PROGRAMME/ZUBEHÖR/ EDITOR). 2. Geben Sie die Systembefehle zum Wechsel in das Klassenverzeichnis und zum Aufruf des Java-Interpreters ein: cd C:\JBProjekte\Kapitel02\ErstesProjekt\classes C:\Compiler\JBuilder40\jdk1.3\bin\java ErstesProjekt.Application1 Die Aufrufe bitte ohne Zeilenumbrüche eingeben! 3. Speichern Sie die Batch-Datei. Rufen Sie den Befehl DATEI/SPEICHERN auf. Wählen Sie das Verzeichnis aus, in dem Sie die Batch-Datei abspeichern wollen. Geben Sie einen passenden Dateinamen mit der Extension .bat an. Wählen Sie als Dateityp ALLE DATEIEN (*.*). Wenn Sie später das Programm aufrufen wollen, brauchen Sie nur noch die Batch-Datei aufzurufen (beispielsweise durch Doppelklick im Windows Explorer). Anwendungen unter Linux starten Wenn Sie unter Linux arbeiten, stehen Ihnen die gleichen Optionen zur Verfügung wie unter Windows, das heißt Sie können Ihre Java-Anwendungen mit Hilfe des JDK-Interpreters von der Konsole aus aufrufen (vergleiche MSDOS-Eingabeaufforderung unter Windows) oder Sie schreiben ein ShellScript für den Aufruf (vergleiche Batch-Datei). 57 Kapitel 2 2.6 Das erste Programm Fragen und Übungen 1. Was ist eine Klasse? Was ist eine Methode? 2. Was ist hier falsch? class dieKlasse { dieKlasse() { } } dieMethode() { // hier kommen die Anweisungen } 3. Welche Bedeutung hat die main()-Methode? 4. Was ist der Rumpf einer Methode? Woran erkennt man ihn? 5. Ist diese Definition der main()-Methode korrekt? public static void main ( String args [] ) { } 6. Wozu dient das Semikolon? 7. Laden Sie das Projekt Ihres ersten Programms (oder legen Sie ein neues Projekt mit einem Anwendungsgerüst an) und scrollen Sie in der Datei Anwendung1.java zur Definition der main()-Funktion. (Zur Erinnerung: Durch Doppelklicken im Projektfenster können Sie eine Datei in den Editor laden.) Löschen Sie das Schlüsselwort static aus der Methodendefinition und versuchen Sie das Programm auszuführen (Taste Ñ). Was erwarten Sie? Was passiert? Haben Sie eine Erklärung dafür? 8. Erweitern Sie Ihr erstes Programm um ein einzeiliges Eingabefeld (JTextField) und schreiben Sie die Ereignisbehandlungsmethode zu dem Schalter um, so dass beim Drücken des Schalters der Text aus dem Eingabefeld in das Label-Feld kopiert wird. 58 Lösungen 2.7 Lösungen 1. Klassen dienen zur Repräsentation der Objekte, mit denen das Programm agieren soll. Sie bestehen aus Daten (den Variablen) und Gruppen von Anweisungen (den Methoden), die auf den Daten operieren. In einer Methode werden logisch zusammengehörige Anweisungen gebündelt. 2. Methoden können nicht außerhalb einer Klasse definiert werden. Das gleiche gilt auch für Variablen. dieMethode() muss also innerhalb der geschweiften Klammer von dieKlasse stehen. 3. Jedes Java-Programm muss eine Methode namens main() haben. Der Computer beginnt die Ausführung des Programms durch Aufruf dieser Methode. 4. Der Rumpf einer Methode wird durch ein Paar geschweifter Klammern markiert. Alles, was innerhalb des Rumpfes definiert wird, gehört zu der Methode. 5. Ja! Wie der Quellcode eingetippt wird, mit wie vielen Returns oder Leerzeichen spielt für den Compiler keine Rolle. Es macht nur dem menschlichen Leser das Leben schwer. 6. Es dient als Endmarke bei der Definition von Variablen und generell bei allen Anweisungen, beispielsweise dem Aufruf einer Methode. 7. Methoden, die nicht als static definiert sind, können nur über Objekte ihrer Klasse aufgerufen werden. Anders ausgedrückt: wenn man möchte, dass eine Methode direkt aufgerufen werden kann, muss man sie als static definieren. An sich ist dies nur selten erforderlich, doch für die main()-Funktion ist es unverzichtbar, da diese beim Programmstart vom Betriebssystem aufgerufen werden soll. Wenn Sie das Schlüsselwort static entfernen, erhalten Sie daher eine Fehlermeldung, dass die main()-Methode nicht gefunden werden kann. 8. Die JTextField-Komponente finden Sie auf der SWING-Seite der Komponentenpalette. Platzieren Sie das Eingabefeld neben dem Schalter und richten Sie Eingabefeld und Schalter aneinander aus. Markieren Sie dazu beide Komponenten. Klicken Sie zuerst auf das Eingabefeld (im UI-Designer oder im Strukturfenster). Drücken Sie danach die Ÿ-Taste und klicken Sie bei gedrückter Ÿ-Taste mit der Maus auf den Schalter. Jetzt sind beide Komponenten markiert und Sie können Sie mit Hilfe der Befehle NACH OBEN AUSRICHTEN und GLEICHE BREITE aus dem Kontextmenü (Klick mit der rechten Maustaste) ausrich- 59 Kapitel 2 Das erste Programm ten. Wenn Sie fertig sind, klicken Sie einfach in den Fensterhintergrund, um die Markierung aufzuheben. Doppelklicken Sie auf die Schaltfläche (dies ist eine Abkürzung, um in den Quelltext der Behandlungsmethode für das Standardereignis der Komponente zu wechseln). Fragen Sie mit getText() den Inhalt des Eingabefeldes ab und übergeben Sie den zurückgelieferten Text an die setText()-Methode des Label-Felds. void jButton1_actionPerformed(ActionEvent e) { jLabel1.setText(jTextField1.getText()); } Sie wissen jetzt, ✘ wie man Komponenten einfügt (über die Komponentenpalette) ✘ wie man Eigenschaften und Ereignisse der Komponenten zur Entwurfszeit konfiguriert (über den Inspektor) ✘ wie man Eigenschaften von Komponenten zur Laufzeit (im Quellcode des Programms) abfragt und ändert (get- und set-Methoden). 60