Java (Programmiersprache)

objektorientierte Programmiersprache
Dies ist eine alte Version dieser Seite, zuletzt bearbeitet am 1. Juni 2005 um 09:09 Uhr durch 217.19.187.198 (Diskussion) (Kritik). Sie kann sich erheblich von der aktuellen Version unterscheiden.

Java ist eine objektorientierte, plattformunabhängige Programmiersprache und als solche ein eingetragenes Warenzeichen der Firma Sun Microsystems. Üblicherweise benötigen Java-Programme zur Ausführung eine spezielle Umgebung (Java Virtual Machine). Der Vorteil ist, dass nur diese Umgebung an verschiedene Computer und Betriebssysteme angepasst werden muss. Sobald dies geschehen ist, laufen auf der Plattform alle Java-Programme ohne Anpassungsarbeiten.

Geschichte

Die Urversion von Java, auch Oak genannt, wurde in einem Zeitraum von 18 Monaten vom Frühjahr 1991 bis Sommer 1992 unter dem Projektnamen "The Green Project" von Patrick Naughton, Mike Sheridan, James Gosling und Bill Joy sowie neun weiteren Entwicklern im Auftrag des US-amerikanischen Computerherstellers Sun Microsystems entwickelt. Einer der Urväter und Hauptentwickler der Sprache war dabei James Gosling. Überbleibsel aus dem Green-Projekt ist der "Duke" von Joe Palrang, der zum bekannten Symbol bzw. Maskottchen geworden ist.

Das ursprüngliche Ziel bei der Entwicklung von Java war aber nicht lediglich die Entwicklung einer weiteren Programmiersprache, sondern die Entwicklung einer vollständigen Betriebssystemumgebung, inklusive virtueller CPU, für unterschiedlichste Einsatzzwecke. Das System sollte - der Legende nach - beispielsweise eine Kaffeemaschine steuern können.

Die Entwicklung fand in einem unauffälligen Bürogebäude in der Sand Hill Road in Menlo Park statt. Während dieser abgeschiedenen Entwicklungsphase kam es zu keinem Austausch mit Sun Microsystems. Im Sommer 1992 schließlich war die erste Oak-basierte Anwendung fertiggestellt – "an interactive, handheld home-entertainment device controller with an animated touchscreen user interface". Diese Technologiedemonstration einer Touchscreen-basierten Gerätesteuerung mit animierter Benutzeroberfläche (GUI) hatte den Namen *7 ("StarSeven").

Nach der Vorführung von StarSeven, mit dem zahlreiche Geräte interaktiv gesteuert werden konnten, wurden Unternehmen aus der Kabelfernseh-Branche aufmerksam und aus dem Hinterzimmer-Projekt "The Green Project" entstand die Firma "FirstPerson". Aus dem Büro wurde ein Bürohaus in der 100 Hamilton Avenue in Palo Alto.

Da die Belegschaft inzwischen von 13 Entwicklern auf 70 Mitarbeiter wuchs und die Zeit für interaktive digitale Mehrwertdienste im Bereich des Kabelfernsehens noch nicht reif war, suchte sich die junge Firma neue Betätigungsfelder. Nach einem dreitägigen Gruppentreffen von John Gage, James Gosling, Bill Joy, Patrick Naughton, Wayne Rosing und Eric Schmidt in "The Inn at Squaw Creek" bei Lake Tahoe war schnell klar: Das Internet war das neue Betätigungsfeld.

Auf Basis des Urvaters aller grafischen Webbrowser, Mosaic, wurde ein um Java erweiterter Browser geschaffen – der "WebRunner" (nach dem Film "The Blade Runner"). Später wurde aus "WebRunner" dann der offiziell bekannte HotJava-Browser.

Im März 1995 wurde die erste Alphaversion (1.0a2) des Java-Quellcodes für die Öffentlichkeit freigegeben und die Downloadzahlen explodierten. Wenig später, am 23. Mai 1995, wurde Java dann erstmals offiziell der Öffentlichkeit vorgestellt, in der "San Jose Mercury News".

Der Durchbruch für Java kam mit der Integration von Java in den Browser Netscape – besiegelt durch einen Handschlag zwischen Eric Schmidt und George Paolini von Sun Microsystems und Marc Andreessen, dem Erfinder und Begründer von Netscape. Ort und Zeit: 4 Uhr morgens in einem Hotelzimmer des Sheraton Palace Hotels in der Nähe des Convention Centers.

Der Name Oak hat seinen Ursprung in einer Eiche (engl. Oak), die vor dem Fenster des Entwicklers James Gosling stand. Dieser Name musste jedoch aufgrund rechtlicher Probleme (es gab bereits eine Software dieses Namens) verworfen werden. Man entschied sich für den Namen Java nach dem Namen einer starken Kaffee-Sorte, die speziell für Espresso Verwendung findet (Java-Bohne) und von den Entwicklern bevorzugt getrunken wurde.

Versionen

Die 1996 erschienene Java-Version 1.0 enthielt noch eine überschaubare Menge von Standardpaketen, die in späteren Versionen schnell anwuchs:

  • java.lang: elementare Klassen, z. B. Object und System
  • java.io: Ein- und Ausgabe
  • java.util: z. B. Datenstrukturen und eine Datumsklasse
  • java.net: einfache TCP/IP-Klassen
  • java.awt: grundlegende Klassen für grafische Benutzeroberflächen
  • java.applet: eine Klasse für die bekannten Applets.

Eine Spracherweiterung wurde 1997 mit Java 1.1 vorgenommen, die Syntax wurde um das Konzept der inneren Klassen erweitert. Dies ging auch einher mit einem Umbau der Ereignisbehandlung hin zu einem Callback-System mit sogenannten Listenern.

Außerdem wurde die Standardbibliothek erweitert:

Java 2 (JDK 1.2) erschien im Jahr 1998. Mit Erscheinen dieser Version sprach Sun von Java 2, dementsprechend heißen die Pakete Java 2 Platform, Standard Edition (J2SE) und statt Java Development Kit (JDK) heißt es Java 2 Software Development Kit (J2SDK).

In dieser Version wurden Just-In-Time-Compiler eingeführt, womit die Ausführung von Java-Programmen deutlich beschleunigt werden konnte. (Für jedes Betriebssystem wird eine eigene Runtime-Bibliothek benötigt.) Die Programme sind aber weiterhin lediglich "vorkompiliert". Die Geschwindigkeit vollständig kompilierter Programme wird nicht erreicht.

Erneut wurde die Standardbibliothek erweitert:

  • neue Schnittstellen und Implementierungen für Collections, also Datenstrukturen wie Listen, Mengen und Maps
  • die Oberflächen-Bibliothek Swing
  • neue Grafik-Funktionen (die Java 2D-API)
  • Drag and Drop-Funktionalität
  • verbesserte Audio-Funktionen
  • eine CORBA-Schnittstelle
  • schwache Referenzen - das sind solche Referenzen, die den Garbage-Collector nicht daran hindern, das referenzierte Objekt zu entfernen

Im Jahr 1998 wurde auch der Java Community Process (JCP) eingeführt. Diese Organisation steuert seitdem Änderungen an der Spezifikation von Java. Für vorgeschlagene Änderungen wird ein Java Specification Request (JSR) erstellt, der verschiedene Phasen durchläuft, bevor die Änderungen in Java Einzug halten.

2000 erschien J2SE 1.3 als nächster Evolutionsschritt, die API wurde erneut erweitert. Des weiteren wurde eine Engine mit Hotspot-Optimierung eingeführt. Das bedeutet, dass nicht mehr der gesamte Bytecode sofort kompiliert wird, sondern nur häufig benutzte Stellen (Hotspots). Codesegmente die sehr häufig ausgeführt werden, werden sogar weiter optimiert, so dass die häufig benutzten Stellen immer schneller ausgeführt werden.

Erst 2002 wurde mit Erscheinen von J2SE 1.4 wieder die Sprache selbst erweitert, was zuletzt bei Version 1.1. geschah. In dieser Version wurde eine Unterstützung für Assertions hinzugefügt. Auch die API wurde wieder erweitert.

Siehe auch: Servlet, Java Web Start, Java Server Pages, J2EE, J2ME, JavaDoc, Blackdown

Java 5.0 erschien am 30. September 2004 als Nachfolger der Version 1.4 – ursprünglich sollte die Version 1.5.0 lauten. In dieser Version gibt es umfangreiche Änderungen an der Sprache selbst sowie weitere API-Erweiterungen:


Die bereits für Java 5.0 geplanten Erweiterungen der Ein-/Ausgabefunktionen (JSR 203) wurden auf Java 6.0 ("Mustang"-Release) verschoben.


Grundkonzepte der Sprache

Der Entwurf der Sprache verfolgte vier Hauptziele:

  1. Objektorientierung
  2. Plattformunabhängigkeit (d. h. Unabhängigkeit vom Betriebssystem und von Hardware)
  3. Vernetzbarkeit
  4. Sichere Ausführung auf fernen Computern

Objektorientierung

Die Sprache Java ist objektorientiert aufgebaut. Die Grundidee der objektorientierten Programmierung ist die softwaretechnische Abbildung in einer Art und Weise, wie wir Menschen auch Dinge der realen Welt erfahren. Die Absicht dahinter ist, große Softwareprojekte einfacher verwalten zu können, und sowohl die Qualität von Software zu erhöhen als auch Fehler zu minimieren. Ein weiteres Ziel der Objektorientierung ist ein hoher Grad der Wiederverwendbarkeit von Softwaremodulen.

Obwohl Java vollständige Objektorientierung unterstützt, gibt es einige wenige Grunddatentypen (int, boolean usw.), die keine Objekte sind (siehe auch Kapitel weiter unten), in der Praxis jedoch stets Verwendung finden.

Reflection

Java bietet eine Reflection-API als Bestandteil der Laufzeitumgebung. Damit ist es möglich, zur Laufzeit auf Klassen und Methoden zuzugreifen, deren Existenz oder genaue Ausprägung zur Zeit der Programmerstellung nicht bekannt war. Diese Möglichkeit ist sonst nur bei Skriptsprachen verbreitet.

Annotationen

Seit Java 5.0 gibt es eine Syntax-Erweiterung namens Annotationen. Sinn der Annotationen ist die automatische Erzeugung von Code und anderen in der Software-Entwicklung wichtigen Dateien für wiederkehrende Muster anhand möglichst kurzer Hinweise im Quelltext. Bislang wurden in Java dafür ausschließlich Javadoc-Kommentare mit speziellen JavaDoc-Tags verwendet, die von Doclets wie z. B. dem XDoclet ausgewertet wurden.

Diese Annotationen können auch in den kompilierten Class-Files enthalten sein, der Quelltext wird also für ihre Verwendung nicht benötigt. Insbesondere sind die Annotationen auch über die Reflection-API zugänglich. So können sie zum Beispiel zur Erweiterung des Bean-Konzeptes verwendet werden.

Plattformunabhängigkeit

Java wird als plattformunabhängige Programmiersprache bzw. plattformunabhängiges System bezeichnet. Die Plattformunabhängigkeit erreicht Java durch die Definition einer eigenen Plattform, der Java-Plattform, die auf den gewünschten Zielsystemen meist durch eine so genannte Java Virtual Machine (kurz: Java VM oder JVM) implementiert wird, der so genannten Java Runtime Environment (JRE).

Die Java Runtime Environment existiert für weit verbreitete Betriebssysteme wie Microsoft Windows, Linux, Solaris, Mac OS X, AIX und viele andere. Daneben gibt es eine JRE nicht nur für Server- und Desktopbetriebssysteme, sondern auch für viele Embedded Systeme wie Mobiltelefone, PDAs, sowie Smartcards und andere technische Plattformen, wie Auto und TV. Die Plattformunabhängigkeit endet jedoch für solche Systeme, für die keine Java Virtual Machine existiert, zumeist ältere oder sehr exotische Systeme.

Java-Programme werden im Normalfall in einen nicht direkt ausführbaren Bytecode übersetzt, den Maschinencode der Java-Plattform. Es gibt auch Compiler für Java, die Java-Quelltexte oder Java-Bytecode in normalen Maschinencode übersetzen können, sowie Prozessoren, die Java-Bytecode als Maschinensprache verstehen und somit direkt ausführen können. Zudem benutzen viele Virtuelle Maschinen einen JIT-Compiler, der zur Laufzeit nativen Code für häufig benutzte Codeteile erzeugt. Damit kann die Ausführungsgeschwindigkeit unter Umständen stark gesteigert werden.

Modulare Ausführung auf fernen Computern

Java bietet die Möglichkeit, Klassen zu schreiben, die in unbekannten Containern ablaufen. Beispielsweise lassen sich Applets in Webbrowsern, die Java unterstützen, ausführen. Das Sicherheitskonzept von Java kann dazu eingesetzt werden, dass unbekannte Klassen dabei keinen Schaden anrichten können, was vor allem bei Applets wichtig ist (siehe auch Sandbox). Beispiele für Java Container-Module sind Applets, Servlets, Portlets, Midlets, Translets, Doclets und Enterprise JavaBeans.

Merkmale der Sprache

Wichtigstes Merkmal von Java ist sein Sicherheitskonzept, das aus drei Schichten besteht:

  1. dem Code-Verifier, der sicherstellt, dass die VM keinen ungültigen Bytecode ausführen kann.
  2. den Class-Loadern, die die sichere Zuführung von Klasseninformationen zum Interpreter steuern.
  3. den Security-Managern, die sicher stellen, dass nur Zugriff auf Programmobjekte erlaubt wird, für die entsprechende Rechte vorhanden sind.

Der Objektzugriff in Java ist über Referenzen genannte Zeiger implementiert, aus Sicherheitsgründen ist es deshalb nicht möglich, mit ihnen zu rechnen oder sie sogar zu modifizieren. So genannte Pointerarithmetik ist mit der Sprache also ausgeschlossen. Per Design können so häufig auftretende Fehler während des Entwicklungsprozesses von vorneherein ausgeschlossen werden.

Um große Projekte strukturieren zu können und saubere Schnittstellen zu Bibliotheken zu schaffen, können die Klassen zu Paketen (englisch packages) zusammengefasst werden. Die Zugriffe auf Klassen und Methoden eines fremden Packages können – ähnlich wie innerhalb einer Klasse unter anderem durch private und public – geregelt werden.

Weiter unterstützt die Sprache Threads (gleichzeitig ablaufende Programmteile) und Ausnahmen (englisch exception) und Java beinhaltet auch einen Garbage-Collector, der nicht (mehr) referenzierte Objekte aus dem Speicher entfernt.

Bemerkenswert ist auch die explizite Unterscheidung von Schnittstellen und Klassen. Eine Klasse kann beliebig viele Schnittstellen implementieren, hat aber stets genau eine Basisklasse. Java unterstützt Mehrfachvererbung insofern, als Schnittstellen, jedoch nicht Klassen, mehrfach vererbt werden können. Funktionen (in der Java-Welt "Methoden") werden nur von der Basisklasse übernommen. Alle Klassen sind – direkt oder indirekt – von der Wurzelklasse Object abgeleitet.

Zu Java gehört eine umfangreiche Klassenbibliothek. Dem Programmierer wird damit eine einheitliche, vom zugrunde liegenden Betriebssystem unabhängige, Schnittstelle (Application programming interface, API) angeboten.

Mit Java 1.1 wurden die Java Foundation Classes (JFC) eingeführt, die u. a. Swing bereitstellen, das zur Erzeugung plattformunabhängiger grafischer Benutzerschnittstellen (GUI) dient und auf AWT basiert.

Syntax

Ein Beispielprogramm, das eine Meldung auf der Konsole ausgibt:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hallo Welt!");
    }
}

Die Grammatik von Java ist in der Java Language Specification dokumentiert.

Grunddatentypen

Grunddatentypen, die auch als 'primitive' oder 'elementare' Datentypen bezeichnet werden, sind in Java die einzigen Datenstrukturen, die keine Objekte sind. Sie sind ebenfalls plattformunabhängig, weil sie stets im Big Endian-Format gespeichert werden. Um dennoch auch primitive Datentypen als echte Objekte behandeln zu können, existiert für jeden einzelnen eine entsprechende Wrapperklasse.

Datentyp Größe¹ Wrapper-Klasse Wertebereich Beschreibung
boolean 8 bit java.lang.Boolean true / false Boolescher Wahrheitswert
char 16 bit java.lang.Character 0 ... 65.535 (z. B. 'A') Unicode-Zeichen (UTF-16)
byte 8 bit java.lang.Byte -128 ... 127 Zweierkomplement-Wert
short 16 bit java.lang.Short -32.768 ... 32.767 Zweierkomplement-Wert
int 32 bit java.lang.Integer -2.147.483.648 ... 2.147.483.647 Zweierkomplement-Wert
long 64 bit java.lang.Long -9.223.372.036.854.775.808 ...
9.223.372.036.854.775.807
Zweierkomplement-Wert
float 32 bit java.lang.Float +/-1,4E-45 ... +/-3,4E+38 Gleitkommazahl (IEEE 754)
double 64 bit java.lang.Double +/-4,9E-324 ... +/-1,7E+308 Gleitkommazahl doppelter Genauigkeit (IEEE 754)

¹: minimaler Speicherverbrauch

Reservierte Wörter

const und goto sind zwar reserviert, aber ohne Funktion, also keine Schlüsselwörter im eigentlichen Sinn. Sie dienen lediglich dem Compiler zur Ausgabe sinnvoller Fehlermeldungen für Umsteiger von C++ oder C.

true, false und null sind Literale, jedoch ebenfalls eigentlich keine Schlüsselwörter im engeren Sinn.

Mit assert werden Assertions realisiert.

private, protected und public sind Zugriffsmodifizierer (access modifier):

Die Klasse selbst Paket-Klassen/
innere Klassen
Unterklassen Sonstige
Klassen
private Ja Nein Nein Nein
(ohne) Ja Ja Nein Nein
protected Ja Ja Ja Nein
public Ja Ja Ja Ja

Private Methoden sind von der Polymorphie ausgenommen, d.h. die Definition einer Methode derselben Signatur in einer Subklasse gilt nicht als Überschreiben.

abstract, final, static sind Polymorphie-Modifizierer. static kann vor allen Membern außer Konstruktoren stehen und bedeutet, dass der betreffende Member im Kontext der Klasse verwendbar ist und kein Objekt benötigt. abstract kann vor Klassen und Methoden stehen und bedeutet, dass dem betreffenden Member Implementierung fehlt. Unterklassen sind gezwungen, sich selbst als abstrakt zu deklarieren oder die fehlende Implementierung zu liefern. final kann vor allen Membern außer Konstruktoren stehen und bedeutet, dass der betreffende Member nicht mehr verändert werden darf. Finale Variablen sind ähnlich wie Konstanten, finale Methoden dürfen von Subklassen nicht überschrieben werden und von finalen Klassen darf man erst gar keine Subklassen bilden. Zugriffe auf finale Variablen, deren Wert dem Compiler bekannt ist, dürfen vom Compiler durch den Wert der Variable ersetzt werden. Aufrufe finaler Methoden dürfen vom Compiler durch eingebundenen Code (Inlining) ersetzt werden. Private Methoden sind automatisch final.

native kann nur vor Methoden stehen und bedeutet, dass die Implementierung der betreffenden Methode nicht in Java, sondern einer anderen Programmiersprache geschrieben wurde, und von der virtuellen Maschine über eine Laufzeitbibliothek gelinkt werden muss.

strictfp kennzeichnet Klassen und Methoden, deren enthaltene Fließkommaoperationen streng nach IEEE ablaufen müssen.

package deklariert die Paketzugehörigkeit eines komplexen Datentyps. Die Namensgebung eines Pakets sollte eindeutig sein und orientiert sich meist an der URI/URL des Eigentümers bzw. Erstellers.

import importiert Symbole (vorher nur Typen, ab 5.0 auch statische Member von Klassen), so dass sie ohne voll qualifizierten Namen verwendet werden können. Der Import kann hierbei über das Wildcard * auf komplete Pakete ausgedehnt werden.

boolean, char, byte, short, int, long, float, double und void sind Typen. void ist der Nichtstyp, notwendig, um Methoden ohne Rückgabewerte zu kennzeichnen. Für die primitiven Typen: siehe oben.

class, interface, enum (ab 5.0) und @interface (ab 5.0) dienen zur Deklaration eigener Typen: Klassen, Interfaces (Schnittstellen für Klassen), Enums (Aufzählungstyp für typsichere Aufzählung, engl. typesafe enumeration) und Annotations für Metadaten. enum und @interface sind mit Java 5.0 in die Sprache aufgenommen worden.

try, catch, finally, throw, throws beziehen sich auf die Ausnahmebehandlung (englisch exception handling). Mit throw wird eine Ausnahme ausgelöst. Alle eventuell ausgelösten Ausnahmen einer Methode, die nicht von RuntimeException oder Error abstammen, müssen mit throws in der Deklaration der Methode (Signatur) angegeben werden. Es handelt sich also um so genannte checked exceptions. Mit try umschließt man einen Block, in dem eventuell eine Ausnahme auftreten könnte. Mit catch fängt man nach einem try-Block die dort aufgetretene Ausnahme ab, mit finally hängt man an einen try- oder catch-Block einen Block für Aufräumarbeiten an (z. B. Schließen von Dateien).

extends und implements dienen der Vererbung: extends der genetischen Erweiterungsvererbung von Klasse zu Klasse oder Interface zu Interface und implements der Implementierungsvererbung von Interface zu Klasse. Außerdem wird extends bei Generics für Typerweiterung verwendet.

super und this beziehen sich im Objekt-Kontext auf das aktuelle Objekt in seinem tatsächlichen Morph (this) bzw. im Morph der Superklasse (super). this wird verwendet, um in Konstruktoren überladene Konstruktoren aufzurufen und um in Membern auf verdeckte Member äußerer Strukturen zu verweisen. super wird in Konstruktoren zum Aufruf des Superklassenkonstruktors und in überschreibenden Methoden zum Aufruf der überschriebenen Methode verwendet. Außerdem wird super bei Generics für Typeingrenzung verwendet.

new reserviert Speicher für neue Objekte (inklusive Arrays) auf dem Heap.

if, else, switch, case, default, while, do, for, break, continue dienen der Bedingungsprüfung und Schleifensteuerung und bedienen sich einer imperativen Syntax.

return liefert Werte aus einer Methode an die aufrufende Methode zurück.

volatile ist ein Modifizierer für nicht-lokale Variablen und verbietet dem JIT-Compiler Registeroptimierungen auf diese Variable, weil mehrere Threads sie gleichzeitig verwenden könnten (insbesondere im Kontext nativer Methoden).

synchronized verwendet ein Objekt als Semaphor mit Lock-Pool und sorgt so dafür, dass jeglicher mit synchronized an denselben Semaphor gebundener Code nur ein einziges Mal gleichzeitig ausgeführt werden kann. Alle anderen Threads, die solche Code-Blöcke ausführen möchten, werden solange blockiert, bis der Semaphor wieder frei ist. Des weiteren dient es auch der Synchronisation eventuell vorhandener lokaler Caches bei Multiprozessormaschinen.

transient kennzeichnet nicht-persistente Variablen, die nicht serialisiert werden dürfen.

instanceof ist ein Java-Operator, der prüft, ob ein Objekt Instanz eines Typs oder Subtyps ist.

Java Plattform

Seit dem Erscheinen von Java 2 wird die Java Plattform in drei Editionen unterteilt, um dem Faktum Rechnung zu tragen daß Java-Applikationen auf vielerlei Endgeräten mit unterschiedlichen Charakteristiken eingesetzt werden kann, von Handys und PDAs über Desktop-Computern bis zu Servern:

  • die Java 2 Platform, Micro Edition (J2ME)
  • die Java 2 Platform, Standard Edition (J2SE)
  • die Java 2 Platform, Enterprise Edition (J2EE)

Unterschiede zu ähnlichen Sprachen

JavaScript

Java ist nicht mit der reinen Skriptsprache JavaScript zu verwechseln, die vornehmlich in HTML-Seiten als eingebettete Programmiersprache verwendet wird. Sie hat eine ähnliche Syntax, unterscheidet sich jedoch in vielerlei Hinsicht und kann insbesondere nicht für die Konstruktion größerer, kompletter Anwendungen verwendet werden. Objekte werden in JavaScript prototypenbasiert definiert. Es gibt Implementierungen vor allem in Web-Browsern, aber auch unabhängige Ausführungsumgebungen sind vorhanden.

C++

Java basiert in Syntax und unmittelbarer Herkunft auf der objektorientierten Programmiersprache C++. Im Gegensatz zu C++ fanden jedoch komplexe Konstrukte wie Mehrfachvererbung oder die fehleranfällige Zeigerarithmetik keinen Einzug. Die interne Speicherverwaltung wird dem Java-Entwickler weitgehend abgenommen; dies erledigt der so genannte Garbage-Collector. Deshalb ist Java in vielen Fällen leichter zu handhaben als C++. Allerdings garantiert auch dieser Mechanismus nicht den vollständigen Ausschluß von sog. "memory leaks" ("Speicherlöcher"); letztlich muss der Programmierer dafür sorgen, dass nicht mehr verwendete Objekte nirgends mehr referenziert werden.

C#

C# (gesprochen: "C sharp" bzw. "ßieh Scharp") kann als Weiterentwicklung von Microsoft von C++ unter Einflußnahme von Java gesehen werden. Mit der Spezifikation von C#, im Rahmen seiner .NET-Strategie, hat Microsoft versucht, den Spagat zu schaffen zwischen dem kompletten Neuanfang einer Sprache und der leichten Integration bisher bestehender Komponenten.

Die Syntax von C# entspricht in großen Teilen der Syntax von Java, konzeptionelle Unterschiede bestehen insbesondere in der Unterstützung von Delegaten (engl. "delegates"), ein Konzept, das am ehesten mit Funktionszeigern vergleichbar ist, hierbei kommt ein Beobachter-Entwurfsmuster zum Einsatz – Objekte können sich für Ereignisse registrieren bzw. diese delegieren. C# kennt ebenso wie Java eine Unterscheidung zwischen Werttypen (engl. "value types"; z. B. int, struct) und Referenztypen (engl. "reference types", z. B. class), allerdings sind auch die elementaren Datentypen objektbasiert. Des weiteren unterstützt C# so genannte Attribute ("attributes"), die es erlauben, die Funktionalität der Sprache über Metadaten im Code zu erweitern (eine ähnliche Funktionalität gibt es seit Java 5.0). C# enthält auch Bestandteile der Sprachen VisualBasic (z. B. Eigenschaften bzw. properties) sowie C++ (z. B. enums). In C# hingegen ist es nicht notwendig und möglich Ausnahmen (exceptions) zu einer Methode zu deklarieren. In Java müssen einmal deklarierte Ausnahmen auch verarbeitet werden.

Um auch systemnahe Programmierung zu ermöglichen, besteht in .NET die Möglichkeit, auch so genannten unsicheren unmanaged code zu verwenden, ähnlich Javas JNI.

Bislang gibt es Microsofts .NET-Implementierung nur für Microsoft-eigene Betriebssysteme (ab Windows NT 4 SP 6). C# ist standardisiert, weswegen das Mono-Projekt und DotGNU eigene Implementierungen vorantreiben, welche auch weitere Betriebssysteme unterstützen.

APIs

Java stellt eine Reihe von Programmierschnittstellen (APIs) zur Realisierung von Softwareprojekten bereit.

Core Java Technology

Desktop Java Technology

Java Shared Data Toolkit (JSDT)

Entwicklungsumgebungen

Datei:Eclipse 3.0.png
Eclipse Java-Perspective (WinXP)

Es gibt eine große Vielfalt von Entwicklungsumgebungen für Java, sowohl kommerzielle als auch freie (Open Source). Die meisten Entwicklungsumgebungen für Java sind selbst ebenfalls in Java geschrieben.

In Form von z. B. OSGi finden sich inzwischen auch eigenständige Entwicklungsframeworks, die verschiedene Konzepte von Java unabhängig hiervon weiterentwickeln - Eclipse basiert beispielsweise auf OSGi. OSGi selbst spezifiziert das Bundle-Konzept, einen service-orientierten Ansatz, um dynamische Nachladbarkeit und Versionsmanagement von Java-Klassen zu ermöglichen (z.B. für Embedded Java-Anwendungen). Hierzu gehört auch das Remote Management von Plattformen, um Service Delivery und Wartung (Updates aus der Ferne) zu ermöglichen.

Die bekanntesten Open-Source-Umgebungen sind Eclipse, jEdit und NetBeans.

Unter den kommerziellen Entwicklungsumgebungen sind das auf Netbeans basierende Sun ONE Studio von Sun, IntelliJ IDEA von JetBrains und JBuilder von Borland am verbreitetsten, sowie JCreator. Außerdem gibt es noch eine, um einige hundert Plugins erweiterte, Version von Eclipse, die von IBM unter dem Namen WebSphere Studio Application Developer ("WSAD") vertrieben wurde und seit Version 6.0 Rational Application Developer ("RAD") heißt.


Wer lieber einen Texteditor verwendet findet in Emacs zusammen mit der JDEE (Java Development Environment for Emacs) ein mächtiges Werkzeug. Für andere Editoren wie Vim oder Jed gibt es ebenfalls entsprechende Modes.

Siehe auch: Cocoon, Jogl

Compiler

Mit einem Java-Compiler ist es möglich Java-Sourcecode (Dateiendung .java) in einen ausführbaren Code zu kompilieren. Grundsätzlich unterscheidet man zwischen Bytecode- und Nativecode-Compilern. Des weiteren verwenden einige Java-Laufzeitumgebungen einen JIT-Compiler um Bytecode häufig genutzter Programmteile in nativen Maschinencode zu übersetzten während das Programm läuft.

Bytecode-Compiler

Java-Programme werden im Normalfall in einen nicht direkt ausführbaren Bytecode (Dateiendung .class) übersetzt, den Maschinencode der Java Plattform der mit der Java Runtime Environment (JRE) interpretiert wird.

Native Compiler

Es existieren auch Compiler für Java, die Java-Quelltexte oder Java-Bytecode in normalen Maschinencode übersetzen können, sogenannte Ahead-Of-Time-Compiler. Nativ kompilierte Programme haben den Vorteil keine JavaVM mehr zu benötigen, aber auch den Nachteil nicht mehr plattformunabhängig zu sein. Hier trifft die Bezeichnung "write once, run anywhere" nicht mehr zu.

  • GCJ
  • Excelsior JET ist ein kommerzieller Java-to-Nativecode-Compiler. Voraussetzung für die Kompilierung ist eine installierte JDK in der Version 1.3/1.4. JET 3 unterstützt alle Java-2-SE-Pakete inklusive AWT/Swing, JNI und Invocation-API.

Wrapper

Ein Wrapper ist ein ausführbares Programm, welches als Ersatz für eine jar Datei dient. Er sucht selbständig nach einer installierten JavaVM, um das Programm zu starten und informiert den Benutzer darüber, wo er eine JavaVM herunterladen kann, falls noch keine installiert ist. Es ist also immer noch eine Laufzeitumgebung nötig, um das Programm starten zu können.

Java Webstart ist ein etwas eleganterer Ansatz für diese Problematik - er ermöglicht die einfache Aktivierung von Anwendungen mit einem einzigen Mausklick und garantiert, dass Sie immer die neueste Version der Anwendung ausführen. Dadurch werden komplizierte Installations- oder Aktualisierungsprozeduren vermieden.

  • JSmooth (Lizenz: GPL)
  • Launch4J (Lizenz: LGPL)
  • Der JBuilder von Borland ist ebenfalls in der Lage einen Wrapper für Windows zu erstellen

Kritik

Ein Problem speziell für Freie Software-Enwickler besteht darin, dass Java nicht frei ist. In diesem Zusammenhang wird auch oft von der "Java Trap" (Java-Falle) gesprochen, womit gemeint ist: In Java geschriebene Programme können Freie Software sein - wer Suns JVM verwendet, nutzt jedoch zur Ausführung der eigenen Freien Software eine proprietäre Software. Da Sun sich beharrlich weigert, die Standardisierung von Java aus der Hand zu geben (wie das z.B. bei C# der Fall ist) und die Sprache bzw. die eigene JVM auch nicht unter einer freien Lizenz veröffentlichen will, wird sich an dieser Situation in absehbarer Zeit nichts ändern. Zum Glück haben aber engagierte Entwickler bereits reagiert und es ist schon eine beachtliche Menge an freier Java-Software zum interpretieren, kompilieren und ausführen entstanden. (z.B.: GNU Classpath, GNU Compiler for Java oder Kaffe). Probleme gibt es hier vor allem dann wenn beim Erstellen von Programmen "unfreie" Klassen von Sun verwendet werden die freie Java Compiler oder VirtualMachines nicht verwenden können. Anwender von freien JVMs sind dann gezwungen auf die proprietäre JVM von Sun zurückzugreifen. Nun ist aber zumindens aus diesem Problem ein Ausweg in Sicht: Die Apache Foundation will mit "Harmony" eine freie Java-Implementierung erschaffen.

Siehe auch: die Java-Falle (Autor: Richard Stallman)

Literatur

Siehe

Programmiersprachen

Programmiersprachen, die sich an Java anlehnen und Bytecode generieren:

Java für Embedded Systems

Java Frameworks

Tutorien

Für Entwickler