Java, Teil 1 – Einführung in eine moderne Sprache

JVM, JFC, Applet, Swing … Viele Begriffe schwirren seit nunmehr 13 Jahren in den Welten der IT herum, die ihren Ursprung in der Sprache Java haben. Dieser Artikel als erster Teil einer kleinen Serie soll die Java-Welt ein wenig beleuchten und den Leser in die Lage versetzen, selbst kleine Programme in Java zu schreiben und Code zu lesen, ohne sich in historischen oder technischen Einzelheiten zu verlieren.

Grundsätzliches

Um ein Java-Programm lauffähig zu machen, sind drei Schritte nötig. Zuerst schreibt der Entwickler den Quellcode als java-Datei. Diese Datei kann nun durch den Compiler in eine class-Datei kompiliert werden. Es entsteht ein Bytecode, der immer noch plattformunabhängig ist. Man kann diesen Bytecode auf jeder Plattform ausführen, auf der die Java-Laufzeitumgebung (JVM – Java Virtual Machine) installiert ist. Der letzte Schritt zur Ausführung ist die Übersetzung des Bytecodes in die Befehle der jeweiligen Plattform durch die Laufzeitumgebung.

Die Wahl des Editors

Es ist eigentlich jeder Editor geeignet, um in Java zu programmieren. Man sollte sich aber den Komfort von Syntaxhervorhebung gönnen, um sich die Arbeit ein wenig zu erleichtern. Für GNOME eignet sich der hauseigene Editor gedit, für KDE beispielsweise Kate. Mit zunehmender Komplexität der Programme möchte man aber auf eine ausgereifte Entwicklungsumgebung zurückgreifen.

Die wichtigsten Umgebungen zur Java-Entwicklung sind ohne Zweifel NetBeans [1] und Eclipse [2]. Beides sind freie Programme, die in den gängigsten Distributionen aus den Paketquellen zu beziehen sind und jeweils ihre eigenen Vorzüge und Schwächen haben. Immer wieder zu beobachtende „Glaubenskriege“ bezüglich der Wahl der Umgebung, die meist ergebnislos ausgefochten werden, sollten von keinem seriösen Entwickler ernst genommen werden. Der offensichtlichste Unterschied ist wohl, dass NetBeans einen grafischen GUI-Builder enthält, mit dem man per Drag & Drop optisch ansprechende GUIs erstellen kann, ohne tiefgehende Kenntnisse über die Swing-Bibliothek [3] zu benötigen.

Andererseits erzeugt NetBeans mit seiner Vorlage für eine grafische Applikation bereits eine erhebliche Menge Code (300 Zeilen), welcher für Einsteiger und vielleicht sogar für Amateure sehr schwer verständlich ist. Es besteht also durchaus die Gefahr, mit dem GUI-Builder in eine Sackgasse zu laufen, wenn man den produzierten Code nicht vollständig versteht. Daher ist ein Einstieg in Swing mit dem GUI-Builder nur eingeschränkt zu empfehlen. Für Eclipse ist ein GUI-Builder bis dato nur in einem kommerziellen Zusatzpaket erhältlich. In der nächsten Ausgabe wird die Grafikprogrammierung unter Java noch ausführlich besprochen, ebenso die Vorbereitung einer Entwicklungsumgebung. In jedem Falle sind beide Umgebungen absolut ausgereift, reich an Features, leicht erweiterbar und nehmen eine absolut gleichberechtigte Stellung im Bereich der professionellen Java-Entwicklung ein.

Installation und Vorbereitungen

Da Sun Java [4] sehr verbreitet ist, werden die meisten Nutzer bereits diese Laufzeitumgebung installiert haben. Um dies zu überprüfen, fragt man die aktuell benutzte Version mitab. Die aktuellste Version von Sun Java ist „1.6.0_16“. Sollte die Versionsabfrage etwas in der Art

$ java -version
java version „1.6.0_10“
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)

java version „1.5.0“
gij (GNU libgcj) version 4.3.2

ausgeben, hat man kein Sun Java, sondern ein anderes Java (hier GNU Compiler for Java [5]) installiert, was aber auch nicht weiter schaden sollte.

Alternativ hilft auch ein Besuch der offiziellen Sun-Testseite [6], die aber natürlich nur ein Ergebnis liefert, wenn Java-Unterstützung im Browser eingerichtet ist.

Nun braucht man noch die notwendigen Bibliotheken, um Programme selbst kompilieren zu können. Zunächst muss man sich nun entscheiden, welche Version von Java man installieren möchte. Das Unternehmen Sun ist Urheber von Java und stellt mittlerweile Versionen für Linux bereit, die zumindest unter der i386- und amd64-Architektur laufen. Man benötigt das JDK (Java Development Kit), welches man nicht mit der JRE (Java Runtime Environment) verwechseln darf, welche nur das Ausführen von Java-Programmen ermöglicht. Das offizielle Java von Sun soll zukünftig unter der GPL veröffentlicht werden, sodass man diesbezüglich wohl keine Bedenken haben sollte. Man installiert das offizielle Java beispielsweise durch das Paket sun-java6-jdk. Die bereits jetzt komplett freie Version OpenJDK lässt sich in den gängigsten Distributionen durch das Paket openjdk-6-jdk installieren. Sollten dennoch außerordentliche Probleme auftreten, hilft Ubuntu-Nutzern die Wikiseite [7] in den meisten Fällen weiter.

Das erste Programm

Das beliebte „Hello World“ ist in Java auf den ersten Blick komplex. Es wird jedoch jeder einzelne Begriff genau erklärt, um niemandem mit Halbwissen und Vermutungen zurückzulassen.

class MyClass {
public static void main(String[] args)
{
System.out.println(„Hello World“);
}
// Dies ist ein einzeiliger Kommentar.

/* Dies ist ein Blockkommentar,
der ueber mehrere Zeilen geht.
*/
}

Listing: MyClass.java

Der Quelltext wird als Datei MyClass.java gespeichert. Danach bewegt man sich in der Konsole in das entsprechende Verzeichnis und kompiliert das Programm mit

$ javac MyClass.java

Anschließend startet man das Programm mit

$ java MyClass

Hinweis: Die Endung .class wird nicht mit angegeben.

Erklärung des Beispiels

Die erste Zeile leitet die Klasse ein, den äußeren Rahmen einer Java-Anwendung. Man beachte, dass der Bezeichner der Klasse (hier MyClass) groß geschrieben wird.

Die zweite Zeile ist die Kopfzeile der Hauptmethode der Klasse, die immer main heißen muss. Eine Methode ist ein Unterprogramm. Hat sie einen Rückgabewert, spricht man von Funktionen, ansonsten auch von Prozeduren. Sie ist der Einstiegspunkt, an dem ein Programm mit der Ausführung beginnt. Die Kopfzeile der Hauptmethode muss in jedem Programm genau so aussehen. public besagt, dass die Methode von außerhalb der Klasse aufgerufen werden kann, static besagt, dass die Methode direkt aus der Klasse aufgerufen wird (ohne Objekt), void legt schließlich fest, dass die Methode keinen Rückgabewert hat. In den runden Klammern steht der Parameter, der dieser Methode übergeben wird. In diesem Falle ein Array (eine Art von Liste) von Strings (Zeichenketten), auf die in der Methode unter dem Namen args (Argument) zugegriffen werden kann.

Nun beginnt eingeschlossen von den geschweiften Klammern der eigentliche Programmcode. Es wird die Methode println aufgerufen, die unter dem Pfad System.out erreichbar ist. Die Methode gibt eine Zeichenkette mit Zeilenumbruch auf der Konsole aus. Diese Zeichenkette wird in runden Klammern übergeben. Am Ende jeder Anweisung muss ein Semikolon stehen (auch wenn es die letzte ist).

Schließlich wird die Klasse noch durch eine geschweifte Klammer geschlossen. Das sind zunächst eine Menge Schlüsselwörter für eine so simple Funktionalität. Doch ist gerade diese strikte Strukturierung unter Java in vielen Situationen vorteilhaft.

Was zeichnet Java aus?

Wie am Beispiel erkennbar, ist Java sehr streng typisiert. Dies ist nicht zu vergleichen mit Sprachen, die auch als Skripte ausgeführt werden können wie zum Beispiel Python. Der Code wird dadurch umfangreicher. Allerdings erkennt der Compiler Fehler im Code sehr präzise und zwingt dem Entwickler einen sauberen und typsicheren Stil auf. Typsicherheit wird bei Java sehr groß geschrieben. Das bedeutet, dass zu jeder Zeit während der Laufzeit des Programms gewährleistet ist, dass eine Variable stets den richtigen Typ hat und so verwendet werden kann, wie es die Programmlogik erfordert. Es kann also nicht passieren, dass ein Programm anstandslos kompiliert, obwohl eine Zeichenkette (String) durch eine ganze Zahl (Integer) dividiert wird (was eine nicht definierte Operation wäre).

Syntaktisches

Die wichtigsten Syntaxregeln sind bereits im Beispiel erkennbar. Klassen, Methoden und Blöcke (logisch zusammenhängende Anweisungen) werden von geschweiften Klammern umschlossen. Jede Anweisung wird mit einem Semikolon beendet. Methoden und Variablen werden mit Angabe ihres Pfades aufgerufen. Unterverzeichnisse werden mit Punkten getrennt.

Fügt man eine weitere Klasse hinzu und legt sie im gleichen Verzeichnis ab wie die andere Klasse, sind sich die Klassen untereinander bekannt.

class MyClass2
{
static String text=“Hallo Welt“;
}

Listing: MyClass2.java

Diese Klasse enthält nur eine Variable, nämlich eine Zeichenkette (String), die text heißt und den Inhalt  Hallo Welt hat. Sie ist als static deklariert, damit sie eine Eigenschaft der Klasse ist, nicht von einem Objekt (dazu später mehr). Diese Klasse lässt sich kompilieren, jedoch nicht ausführen. Es fehlt die main-Methode. Doch die Klasse aus dem ersten Beispiel kann nun auf die Variable der zweiten Klasse zugreifen. Man ergänze die Hauptmethode der Klasse MyClass durch die Anweisung

System.out.println(MyClass2.text);

Sind beide Klassen (neu) kompiliert, wird auf der Konsole nun auch  Hallo Welt ausgegeben:

$ javac MyClass.java
$ javac MyClass2.java
$ java MyClass
Hallo Welt

Primitive Datentypen und Mathematik

In Java kann man sehr ähnlich wie in jeder anderen Programmiersprache mathematische Operationen durchführen. Die gängigsten Datentypen und Operationen sollen im folgendem Beispiel gezeigt werden.

class Beispiel {

public static void main(String[] args) {

 

// Die Variable zahl1 wird deklariert.

int zahl1;

 

// zahl1 wird initialisiert es wurde

// ihr ein Wert zugewiesen.

zahl1 = 7;

 

// zahl2 wird in einer Anweisung

// deklariert und initialisiert.

int zahl2 = 3;

System.out.println(zahl1 + zahl2);

// Ausgabe: 10

System.out.println(zahl1 * zahl2);

// Ausgabe: 21

System.out.println(zahl1 / zahl2);

// Ausgabe: 2
// „double“ ist genauer

double zahl3 = 7.0;
System.out.println(zahl3 / zahl2);

// Ausgabe: 2.33333…

}

}


Listing: Beispiel.java

Warum wird bei der ersten Division als Ergebnis der Wert 2 ausgegeben? In dem Beispiel wird mit ganzen Zahlen (int) gerechnet. Die Nachkommastellen werden einfach abgeschnitten. Wird ein genaues Ergebnis gewünscht, muss ein anderer Datentyp benutzt werden, wie zum Beispiel double.

Klassen und Objekten

Objekte können in Java für nahezu alle greifbaren Elemente des Programms stehen. Diese können simpel (eine Zahl) oder komplex (eine Liste von Hashmaps, in denen offene Datenbankverbindungen auf die jeweiligen Nutzer abgebildet werden) sein. Eine Tatsache muss allerdings beachtet werden: Primitive Datentypen sind in Java keine Objekte. Dies sind beispielsweise int oder double (später dazu mehr). Jedes Objekt hat einen bestimmten Typ. Im Beispiel MyClass2 ist die Variable text ein Objekt vom Typ String. Somit ist sichergestellt, dass ein Objekt nur so benutzt werden kann, wie es für seinen Typ definiert ist. Ist für Objekte des Typs „Turnschuh“ beispielsweise die Methode „volltanken“ nicht definiert, obwohl sie im Code aufgerufen wird, würde der Compiler dies sofort erkennen.

Eine Klasse ist in Java nichts anderes als ein Bauplan für Objekte eines bestimmten Typs. Der Bezeichner der Klasse ist gleichzeitig der Bezeichner des Typs der Objekte, die Instanzen dieser Klasse sind.

class Person {
public String vorname;
public String nachname;

public void printName()
{
System.out.println(vorname+“ „+nachname);
}
}

Listing: Person.java

Es wurde ein neuer Datentyp namens Person erzeugt. Man beachte, dass die beiden Variablen vorname und nachname nun nicht als static deklariert werden. Das hat zur Folge, dass jedes Objekt vom Typ Person nun die beiden Variablen „hat“. Jede Person hat ihre eigenen Variablen. Somit sind die Variablen keine Eigenschaften der Klasse mehr, sondern von den Instanzen, die sie erzeugt. Die Methode printName ist ebenfalls nicht statisch, sie wird also nur von Objekten aufgerufen. Die runden Klammern nach dem Bezeichner sagen aus, dass die Methode keinen weiteren Parameter erwartet. Sie gibt den Vornamen, gefolgt von einem Leerzeichen (Zeichenketten werden mit + verbunden), und dann den Nachnamen auf der Konsole aus.

Das nächste Beispiel Person2.java erzeugt nun eine Person, weist den Variablen Werte zu und ruft die Methode printName auf.

class Person {
public String vorname;
public String nachname;

public void printName()
{
System.out.println(vorname+“ „+nachname);
}

public static void main(String[]args)
{
Person einePerson = new Person();
einePerson.vorname = „Hans“;
einePerson.nachname = „Maier“;
einePerson.printName();
}
}

Listing: Person2.java

Was geschieht in diesem Programm? Der Einstiegspunkt ist wieder die main-Methode. Es wird eine Variable vom Typ Person mit dem Bezeichner einePerson deklariert. Dieser Variable wird ein neu erzeugtes Objekt zugewiesen, das durch new erzeugt wird. Dadurch wird der sogenannte Konstruktor aufgerufen, der eine Methode ist, die ein neues Objekt zurückgibt. Hier steht kein Parameter in den runden Klammern, da der immer implizit vorhandene parameterlose Konstruktor aufgerufen wird. Nun kennt die Laufzeitumgebung eine Person mit dem Bezeichner einePerson, die jedoch noch keine zugewiesenen Werte für vorname und nachname hat. Dies ändert sich in den nächsten beiden Anweisungen. Über die Punktnotation werden die Variablen aufgerufen, und ihnen ein Wert zugewiesen. Letztendlich werden diese Variablen durch Aufruf von printName mit der Person einePerson auf der Konsole ausgegeben.

Weiterführendes zu Klassen

Das Klassenkonzept kann sehr intuitive Programmierung ermöglichen. Es ist beispielsweise möglich, mit dem Schlüsselwort extends eine Klasse aus einer anderen Klasse abzuleiten. Man spricht von Vererbung. Man könnte etwa eine Klasse Mitarbeiter erstellen, welche die Variable personalnummer (deklariert als int, also als ganze Zahl) enthält, und diese Klasse von Person ableiten. Jeder Mitarbeiter hätte damit automatisch auch die Variablen vorname und nachname, sowie die Methode printName, ohne dass man dies noch einmal in den Code schreiben muss. Die Syntax wäre:

class Mitarbeiter extends Person {
public int personalnummer;
}

Listing: Mitarbeiter.java

Nun „ist“ jeder Mitarbeiter auch eine Person. Und alle Methoden die für eine Person definiert sind, können auch von einem Mitarbeiter aufgerufen werden. Umgekehrt ist das natürlich nicht der Fall. Eine Person, die kein Mitarbeiter ist, hat die Variable personalnummer nicht. Der Compiler würde dies bemerken.

Es kann jedoch auch zu sehr abstrakten Beziehungen zwischen den Klassen kommen, die nicht unbedingt dem intuiven Verständnis entsprechen. Es ist beispielsweise möglich, dass ein Objekt eine Variable hat, die eine Liste ist, in dem das Objekt selbst noch einmal enthalten ist. Der Fantasie sind dort keine Grenzen gesetzt. Man denke nur an ein Kind, dass seinen Vater als Variable hat, während der Vater auch seine Kinder als Variablen hat.

Ausblick

Im nächsten Teil der Serie wird die Grafikprogrammierung mit Java ausführlich beschrieben.

Links

  1. http://www.netbeans.org/
  2. http://www.eclipse.org/
  3. http://de.wikipedia.org/wiki/Swing_(Java)
  4. http://www.java.com/de/
  5. http://gcc.gnu.org/java/
  6. http://www.java.com/de/download/help/testvm.xml
  7. http://wiki.ubuntuusers.de/Java

Advertisements

Eine Antwort to “Java, Teil 1 – Einführung in eine moderne Sprache”

  1. Lustig, ich hätte garnicht gedacht das das *wirklich* so funktioniert. Komische Welt.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: