5 Aufbau und Anwendungspotentiale von Java

5.1 Aufbau und Konzepte

In diesem Kapitel soll ein Überblick über die Konzepte von Java gegeben werden. In der Knappheit, die diesem Dokument auferlegt wurde, können natürlich nicht alle Aspekte mit der nötigen Tiefe erörtert werden. Es wurde jedoch versucht alle Besonderheiten der Sprachkonzepte Javas zu würdigen.

5.1.1 Kurzeinführung in JAVA

Was ist JAVA?

JAVA ist eine Programmiersprache.

Beim Design von Java wurde versucht die Goodies der bekannten Programmiersprachen zu übernehmen und deren Nachteile die sich im Laufe deren Existenz gezeigt haben auszubügeln. Java ist rein objektorientiert und hat keine strukturellen Überbleibsel, wie das z.B. in C++ der Fall ist. Java sollte alles enthalten, was das Programmieren angenehm macht und dabei mit einer klar überschaubaren und redundanzfreien Syntax auskommen.

Nach SUN (http://java.sun.com/java.sun.com/allabout.html):

Java is a simple, robust, object-oriented, platform-independent multi-threaded, dynamic general-purpose programming environment. It’s best for creating applets and applications for the Internet, intranets and any other complex, distributed network.

Java entstand aus der deprimierenden Erfahrung Suns, dass die vorhandenen “neuen” Programmiersprachen mit neuen Programmierparadigmen keinesfalls eine revolutionäre Erleichterung in der Softwareentwicklung mit sich brachten. Java soll nun endlich die Vorzüge neuer Entwicklungsmethoden auf die Ebene der Programmiersprache bringen und dem Programmierer das “Leben” erleichtern.

Was kann JAVA?
Java kann nicht mehr und nicht weniger als andere Programmiersprachen auch. Durch die Konzeption eignet sich Java jedoch für eine Fülle von Anwendungen die Plattformunabhängigkeit macht Java z.B. zur idealen Programmiersprache für verteilte Anwendungen, insbesondere im WWW. Dabei bleibt der Anspruch auf Portabilität nicht im leeren Raum (man erinnert sich noch vage an die Aussage das C eine portable Programmiersprache ist) , der praktische Einsatz verschiedener Java Applikationen und insbesondere der Applets zeigt, dass Java durch seine Konzepte wirklich auf den unterschiedlichsten Plattformen lauffähig ist.

Verschiedene große Betriebsystem Hersteller wollen Java als Bestandteil in ihre Betriebsysteme integrieren. Dazu gehören z.B. Micro$oft, IBM und Apple.

Was kann JAVA nicht?
Kaffee kochen.

5.1.3 Was fällt weg? (im Vergleich zu C/C++)

Keine Strukturen, Aufzählungstypen, Unions
Die Aufzählungstypen (z.B. enum), Strukturen und Unions können in Java, wie in jeder objektorientierten Programmiersprache, durch geeignete Klassen dargestellt werden. Deshalb sind explizite Typendefinitionen unnötig. Dieser Schritt, typedefs, enums etc. aus C++ zu entfernen war wegen der gewünschten “Kompatibilität” zu C nicht möglich. In Java wird durch diese Maßnahme die Syntax wesentlich schlanker und auch die Probleme der Namensraumvergabe wird durch die dann nötigen zugehörigen Klassen vermieden. (In C haben z.B. alle enum Typen einen eigenen, gemeinsamen Namensraum)

Keine Funktionen
Alleinstehende Funktionen, die nicht Methoden einer Klasse sind, werden nicht unterstützt. Das vermeidet Mehrdeutigkeiten und Widersprüche in der Klassenhierarchie. Java unterstützt Klassenmethoden und Klassenvariablen, wodurch alleinstehende Funktionen unnötig werden.

Keine Header Files

In Java werden die Klassen komplett in einem File Codiert. Header Files wie in C gibt es nicht. Zu jeder Klasse wird ein eigenes Klassenname.class File erzeugt. Dadurch kann es z.B. nicht mehr vorkommen, dass durch Änderungen in einer Zentralen Klasse in einem Header File das gesamte Projekt neu Übersetzt werden muss. Der Einsatz von Java macht Hilfsmittel wie make und trickreiche Compilerfeatures, die versuchen dieses Problem zu minimieren unnötig.

Kein Überladen von Operatoren
Java unterstützt kein Operator Overloading. Diese Möglichkeit war bzw. ist schon immer umstritten. Sun hat der Regel der Einfachheit und Klarheit Vorrang gegeben. Die Möglichkeiten des Operator Overloadings kann durch Klassenmethoden einfach ersetzt werden.

Kein Precompiler (z.B. #DEFINE)
Precompiler, wie man sie von C oder C++ her kennt, werden von Java nicht eingesetzt. Der durchgängig objektorientierte Ansatz soll einen Precompiler unnötig machen. Globale Definitionen von Konstanten können als Klassenvariablen (static) realisiert werden. Dadurch bekommen die Konstanten auch einen eigenen Namensraum, was widersprüchliche Bezeichnernamen ausschließt. Diverse Tricks und auch Fehlerquellen werden so ausgeschlossen.

Keine vage definierte Datentypen
In Java sind die primitiven Datentypen, anders als in C vollständig definiert. So ist ein int immer 32 Bit breit und mit Vorzeichen behaftet. Es gibt anders als in C feste Definitionen für die Basis Datentypen. Die übrigens die einzigen Typen sind die keine Klasse darstellen. Durch Vererbung können ihnen jedoch weitere Methoden zugeordnet werden.

Die direkte Implementierung von Basis Datentypen in die Programmiersprache verbessern das Laufzeitverhalten, gegenüber Typenlosen Programmiersprachen wie zum Beispiel Smalltalk, enorm.

Keine (expliziten) Pointer und keine Pointerarithmetik
Java hat zum Ziel, eine möglichst sichere Laufzeitumgebung zur Verfügung zu stellen. Aufgrund der Möglichkeit, komplexe Strukturen mit Hilfe von Klassenhierarchien darzustellen, ist Java nicht auf Pointerarithmetik angewiesen. In Java gibt es generell keine expliziten Pointer, womit ein weiterer Großteil der Fehlermöglichkeiten herkömmlicher C und C++ Programme ausgeschlossen werden.

Keine vargs (freie Argumentenanzahl)
Java unterstützt keine Funktionen mit variabler Argumentenanzahl wie es z.B. in C bei der Funktion printf verwendet wird. Auch hier stellt der objektorientierte Ansatz geeignetere und weniger fehlerträchtige Möglichkeiten zur Verfügung (wie es schon in C++ mit cout realisiert wird).

Keine Mehrfachvererbung
Die gewaltigen Probleme die durch den Einsatz von Mehrfachvererbungen auftreten können sind dadurch umgangen werden, dass es diese Möglichkeit nicht gibt. Durch den Einsatz von Interfaces die einen Satz von Schnittstellenmethoden definieren, die in der Klasse implementiert werden, wird eine weitgehend vergleichbare Funktionalität ohne die bekannten Probleme erreicht. Diese Interfaces wurden den protocols in Objective C nachempfunden.

Kein Semikolon oder doch Semikolon
Beim Design von Java wurde darauf geachtet, dass der Programmierer nicht mit irgendwelchen “; erwartet” Fehlermeldungen zu kämpfen hat. Wo es die Grammatik erlaubt ist der “;” optional oder kann beliebig oft gesetzt werden. Bei der Entwicklung der Sprache wurde auch darauf geachtet, das der Compiler die Möglichkeit hat Fehler genau zu lokalisieren. Die in C übliche Fehlermeldung mit Verweis auf eine Zeile die auf die eigentlich fehlerhafte Zeile mit fehlendem Semikolon folgt sollte in Java nicht vorkommen.

5.1.4 Speicherverwaltung
Als erste Besonderheit, insbesondere für nicht Smalltalk Programmierer ist das Konzept der Speicherverwaltung in Java zu nennen. In Java gibt es keinen Heap auf dem dynamische Daten allociert werden, also auch kein malloc oder mfree. Vielmehr sorgt die Java Laufzeitumgebung selbst dafür, das nicht mehr benötigte Objekte automatisch freigegeben werden. Dazu trägt jedes Objekt einen Zähler mit sich, wie viele Verweise auf das Objekt noch existieren.

Die Arbeit selbst dafür zu sorgen das Objekte rechtzeitig freigegeben werden, die z.B. in C++ bei komplexeren Programmen extreme Ausmaße annimmt entfällt also völlig. Man spricht von einem Garbage Collector. In Java läuft dieser Garbage Collector in einem eigenen Task mit niederer Priorität, das Aufräumen wird also im Hintergrund erledigt.

Speicherleichen, also Objekte die nicht mehr benötigt werden, deren Speicher jedoch nicht freigegeben wurde gehören automatisch der Vergangenheit an. Es kann auch nicht mehr vorkommen das eine Referenz auf ein nicht mehr allociertes Objekt existiert, was bei C und C++ zu häufigen Fehlern geführt hat (z.B. eine durch eine lokale Funktion deklarierte Variable wird per Pointer dem Aufrufer bekanntgegeben).

Dieses Konzept tritt nicht nur auf Objekte sondern auch für Klassen in Kraft, da Klassen in Java nichts anderes sind als von der Klasse Objekt abgeleitete Objekte. Das heißt insbesondere das zur Laufzeit eines Programms nur die Klassen im Hauptspeicher gehalten werden die auch wirklich gebraucht werden. Das hat zur Folge, dass beim Programmstart zunächst nur die Basisklassen z.B. der awt Library geladen werden, was allerdings auf Grund des dynamischen Linkvorgangs, der gleichzeitig einsetzt merklich Zeit in Anspruch nimmt.

5.1.5 Threads
Java verwendet selbst z.B. zur Realisierung der Speicherverwaltung Threads und es bietet dem Programmierer Klassen und Methoden zur Threadbildung zur Verfügung. Threads ermöglichen das parallele Ausführen einzelner Programmteile. Bei GUI basierenden Systemen ist es z.B. wichtig das verschiedene Aufgaben parallel erledigt werden. So will der Anwender in der Menüstruktur blättern, während in einem Fenster Berechnungen ausgeführt werden und in einem anderen gerade eine Grafik aufgebaut wird.

Bei Java muss sich der Programmierer nicht mehr mit den Besonderheiten der Zielplatform auseinandersetzen und er muss auch keine Bedenken haben ob die standard Library Funktionen reentredant (sprich mehrfach gleichzeitig aufgerufen werden dürfen) sind. Er bekommt durch Java einheitliche Methoden zur Synchronisation von Threads und zur Kommunikation zwischen verschiedenen Threads zur Verfügung gestellt. Durch den Modifizierer synchronized können Methoden eines Objekts gegen mehrfachen parallelen Aufruf geschützt werden. Ein in der Java Laufzeitumgebung implementierter Monitor überwacht dann das diese Methoden des Objekts nicht parallel sondern seriell Ausgeführt werden. Generell sollten alle Methoden die Objektatribute verändern als synchronized deklariert werden.

Die Standardbibliothek ist vollständig “Threadfest”, das heißt Methoden kann uneingeschränkt mehrfach parallel aufgerufen werden.

5.1.6 Benennungskonventionen
Wie schon mehrfach erwähnt werden in Java Klassen unter ihrem Realnamen abgelegt. Dadurch muss man beachten, dass ein File mit dem Namen test.java nach der Compilierung unter Umständen mehrere Files erzeugt die zum Beispiel klasse1.class, klasse2.class etc. heißen. Zum Auffinden der Klassen wird vom ClassLoader der Klassen eine bestimmte Strategie verfolgt (wie Eingangs erwähnt kann der ClassLoader auch überladen werden und dadurch sein Verhalten verändert werden). Klassen werden zu sogenannten Packages zusammengefaßt. Bestes Beispiel sind die standard Librarys deren Namen alle mit dem Prefix java. beginnen. Um den Anspruch an die Dateisysteme nicht übergebühr zu erhöhen wird zum Beispiel für die Klasse java.awt.list der Filenamen list.class Verzeichnis .\java\awt\ verwendet.

Inzwischen ist man dazu übergegangen die kompletten Librarys in einem Archiv zu speichern (CLASSES.ZIP). Dieses File darf bei der Installation von Java keinesfalls ausgepackt werden.

Zur Benennung von Klassen die (Inter-) Netz weit bekannt sein sollen, gilt die Konvention als Prefix der Klassen den eigenen URL zu verwenden (dadurch wäre es mit einem geeigneten ClassLoader möglich Klassen automatisch in der aktuellsten verfügbaren Version vom durch den URL zu identifizierenden Server zu Laden).

 

Wurde dir weitergeholfen? Hilf anderen Schülern!

Referate hochladen