Java ist eine objektorientierte, plattformunabhängige Programmiersprache und als solche ein eingetragenes Warenzeichen der Firma Sun Microsystems. Java-Programme benötigen zur Ausführung eine spezielle Umgebung, die Java-Laufzeitumgebung oder Java-Plattform genannt wird und als wichtigsten Bestandteil die Java Virtual Machine enthält. 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. Die Programmiersprache Java ist eine Komponente der Java-Technologie.
Java
| |
---|---|
![]() | |
Basisdaten
| |
Entwickler | Sun Microsystems |
Erscheinungsjahr | 1995 |
Aktuelle Version | 5.0 (30. September 2004) |
Betriebssystem | Windows, Linux, Mac OS X, Solaris |
Kategorie | Objektorientierte Programmiersprache |
Lizenz | BCL |
deutschsprachig | ja |
java.sun.com |
Grundkonzepte der Sprache
Der ursprüngliche Entwurf der Programmiersprache Java strebte im wesentlichen fünf Ziele an.
- Sie soll eine objektorientierte Programmiersprache sein.
- Sie soll es ermöglichen, dass gleiche Programm auf unterschiedlichen Computersystemen auszuführen.
- Sie soll eingebaute Unterstützung für die Verwendung von Computernetzen enthalten.
- Sie soll Code aus entfernten Quellen sicher ausführen können. Dieser Punkt wird über das Sicherheitskonzept von Java erreicht, das aus drei Schichten besteht:
- dem Code-Verifier (deutsch "Code-Überprüfer"), der sicherstellt, dass die VM keinen ungültigen Bytecode ausführen kann.
- den Class-Loadern (deutsch "Klassenlader"), die die sichere Zuführung von Klasseninformationen zum Interpreter steuern.
- den Security-Managern (deutsch "Sicherheitsverwalter"), die sicher stellen, dass nur Zugriff auf Programmobjekte erlaubt wird, für die entsprechende Rechte vorhanden sind.
- Die "guten" Teile älterer objektorientierter Programmiersprachen wie C++ sollen für Java-Programmierer weiterhin zur Verfügung stehen. Daher rührt die ähnliche Syntax.
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.
Ein neuer Aspekt von Java gegenüber den zuvor am meisten verbreiteten objektorientierten Programmiersprachen C++ und Smalltalk ist die explizite Unterscheidung zwischen Schnittstellen und Klassen, die auch durch entsprechende Schlüsselworte interface
und class
zur Geltung kommt.
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
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 Überschrieben.
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 komplette 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.
Unterschiede zu ähnlichen Sprachen
JavaScript
Java ist nicht mit der reinen Skriptsprache JavaScript zu verwechseln, die vornehmlich in HTML-Seiten zur eingebetteten Programmierung 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 Ausschluss von Speicherlecks. Letztlich muss der Programmierer dafür sorgen, dass nicht mehr verwendete Objekte nirgends mehr referenziert werden.
C#
C# (gesprochen: "C sharp" bzw. "ßieh Scharp"), entwickelt von Microsoft, kann als Konkurrenzprodukt zu Java gesehen werden. Mit der Spezifikation von C# hat Microsoft im Rahmen seiner .NET-Strategie versucht, den Spagat zwischen dem kompletten Neuanfang einer Sprache und der leichten Integration bisher bestehender Komponenten zu schaffen.
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 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) - abgesehen von einer Referenz-Implementierung für das FreeBSD-Betriebssystem, die aber unter der sogenannten Shared Source-Lizenz (Quellcode-Modifikationen dürfen nicht weitergegeben werden) veröffentlich wurde, weswegen das Mono-Projekt und DotGNU eigene Implementierungen vorantreibt. Dabei werden auch weitere Betriebssysteme unterstützt. Dies wird dadurch vereinfacht, dass C# standardisiert ist.
Entwicklungsumgebungen
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.
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.
- javac (Teil des J2SDK) von Sun Microsystems
- Jikes von IBM
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.
- GNU Compiler for Java
- 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
Literatur
- James Gosling, Bill Joy, Guy Steele, Gilad Bracha: The Java Language Specification. Second Edition.
- David Flanagan: Java in a Nutshell (Deutsche Ausgabe). O'Reilly, 2002, ISBN 3-89721-332-X
- Core Java 2: Band 1 - Grundlagen Einführung in die objektorientierte Programmierung von Horstmann, Cay S. / Cornell, Gary ISBN 3-8273-2216-2
- Guido Krüger: Handbuch der Java-Programmierung. Addison-Wesley, 2002, ISBN 3-8273-1949-8 (Freier Download)
- Christian Ullenboom: Java ist auch eine Insel. Galileo Computing, 2004, ISBN 3-89842-365-4 (Online-Buch)
- Friedrich Esser: Java 2 – Designmuster und Zertifizierungswissen, Galileo Computing, 2001, ISBN 3-9343-5866-7 (Online-Buch)
- Boris Schäling: Programmieren in Java (Online-Buch)
- Bruce Eckel: Thinking in Java, Prentice-Hall, 2002, ISBN 0-1310-0287-2 (Online-Buch, Englisch)
- Joshua Bloch: Effective Java Programming Language, Addison-Wesley, 2001, ISBN 0201310058
- Dietrich Boles, Cornelia Boles: Objektorientierte Programmierung spielend gelernt mit dem Java-Hamster-Modell, Teubner, 2004, ISBN 3-519-00506-9
- Ralph Steyer: Java 2 - M+T Pocket, Das Programmier-Handbuch, ISBN: PDF-3-8272-6106-6, Markt & Technik, 2003 (Online-Buch)
Siehe
Programmiersprachen
Programmiersprachen, die sich an Java anlehnen und Bytecode generieren:
Java für Embedded Systems
Java Frameworks
Java-basierte Plattformen
- Multimedia Home Platform (MHP)
- MIDP
Weblinks
- Java-Abteilung von Sun Microsystems (Englisch)
- Download Java (Englisch)
- Kaffee & Kuchen Deutsche Java-Seite mit News & Workshops
- Entwicklung einer Java-VM für .NET
Tutorien
- Interaktives Java Tutorial von Bradley Kjells (dt./engl.), einsteigerfreundliche Einführung in Java
- Java Tutorial von Sun (engl.)
- LaLiLuna Tutorials Anleitungen zu Struts Webframework, Struts Tiles, Java Server Faces, JSP und Servlets, Hibernate, EJB (Enterprise Java Beans) (deutsch/englisch)
- Erstellen von Spielen und Bewegung mit Java 1.4: javacooperation (deutsch/englisch/russisch)
- Das Java 2 Magnum von Ralph Steyer, ISBN: 3-8272-6242-9, Markt & Technik ist vollständig online gestellt Java Magnum.
Für Entwickler
- Java-Dokumentation der aktuellen Version J2SE 1.5 (Englisch, inkl. Sprachdefinition und Standard-API)