|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
HOME | COURSES | TALKS | ARTICLES | GENERICS | LAMBDAS | IOSTREAMS | ABOUT | CONTACT | | | | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Java 7 - Überblick
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Die Freigabe der Version 7 von Java ist für Mitte 2011 angekündigt. Wir wollen in diesem Beitrag einen Überblick über die zu erwartenden Neuerungen geben und uns einige der neuen Sprachmittel und JDK-Ergänzungen in nachfolgenden Beiträge genauer ansehen. Die Version 7 von Java hat lange auf sich warten lassen. Das liegt unter anderem daran, dass im Januar 2010 die Firma Sun Microsystems vom Software-Konzern Oracle übernommen wurde und damit die Verantwortung für Java und den JDK an Oracle übergegangen ist. Wie vermutlich jede Firmenübernahme führte es Neuorientierungen, Umorganisationen und allerlei strategischen und organisatorischen Neuausrichtungen, die in diesem Falle die Freigabe der Version 7 von Java beeinflusst und verzögert haben. Aber auch schon vor dieser Firmenübernahme war Java 7 in keinem überzeugenden Zustand. Der Community Process (JCP), in dem bis dahin die wesentlichen Weiterentwicklungen von Java besprochen, spezifiziert und verabschiedet worden waren, hatte sich seltsam aufgelöst. Das dürfte wesentlich an den Streitigkeiten zwischen der Apache Software Foundation und Sun Microsystems im Zusammenhang mit dem Apache Harmony JDK gelegen haben. Aber auch verschiedene technische Themen waren extrem umstritten in der Java Community - Closures/Lambdas und die Modularisierung gehören zu diesen Streitpunkten. Die Meinungsverschiedenheiten hatten dazu geführt, dass es zwar Implementierungen für einige Neuerungen gab, aber keinerlei Konsens und auch keine Spezifikation dessen, was implementiert worden war. Das Ergebnis war ein JDK 7, nämlich der OpenJDK, zu dem Sun Microsystems die maßgeblichen Beiträge geleistet hat. Aber es gab kein Java 7, also keine Festlegung dessen, was eigentlich die Version 7 von Java ausmacht. Interessanterweise gab es aber einen (noch von Sun Microsystems veröffentlichten) Meilensteinplan, in dem die Freigabe von Java 7 für den 9. September 2010 angekündigt war. Genau an diesem Stichtag sah sich Oracle dann veranlasst zu verkünden, dass es leider zu diesem Zeitpunkt keine Freigabe geben werde. Eine wirkliche Überraschung war es nicht, denn wesentliche Teile der geplanten Features waren weder spezifiziert noch implementiert und getestet.
Der neue Freigabeplan vom September 2010 sieht nun eine Teilung des
ursprünglich für Java 7 geplanten Umfangs in eine Version 7 von
Java "Mitte 2011" und eine Version 8 von Java "Ende 2012" vor. Seit
dem November 2010 gibt es auch vier JSRs (Java Specification Requests),
die die Neuerungen in Java 7 und 8 beschreiben (siehe /JSRQ/). In diesem
und den nächsten Beiträgen werden wir anschauen, was es Neues
geben wird. Hier ist eine Übersicht über die wesentlichen
Neuerungen; die vollständige Liste ist unter /FEAT/ zu finden.
Worum geht es dabei?
Project Coin"Project Coin" (siehe / COIN /) ist eine Sammlung kleinerer Spracherweiterungen. Die Ideen für diese Ergänzungen stammen aus der Java Community selbst. Sun Microsystems hatte die Community aufgefordert, entsprechende Vorschläge zu machen, und hatte aus der Fülle der Ideen eine Handvoll aufgegriffen. Die Idee dabei war es, die Sprache um Mittel zu erweitern, die nützlich und "klein" sind.In den JDK geschafft haben es folgende Vorschläge:
Lediglich der Diamond-Operator hat das Potenzial, noch einmal substantiell umgekrempelt zu werden. Er setzt auf die Type Inference Algorithmen des Compilers auf. Diese könnten sich im Zusammenhang mit "Project Lambda" ändern. Project Lambda ist erst für Java 8 vorgesehen; die Spezifikation ist noch nicht fertig; heute kann niemand absehen, wie die Lambdas am Ende aussehen werden und welche Rückwirkungen ihre Implementierung auf den Diamond-Operator haben werden. Die Sprachunterstützung für Collections ist noch nicht implementiert und deshalb nicht für Java 7 vorgesehen, sondern gleich auf Java 8 verschoben worden. Auch hier ist zu erwarten, dass die später frei gegebene Implementierung von den heutigen Vorschlägen abweichen wird.
Die "Coin"-Features werden wir uns in den nächsten beiden Beiträgen
genauer ansehen.
InvokeDynamicinvokedynamic (siehe /JSR292/) ist eine neue ByteCode-Instruktion, die den Aufruf von Methoden erlaubt, ohne dass geprüft wird, zu welcher Klasse diese Method gehört, von welchem Typ ihr Returnwert ist oder welche Methodenparameter sie verwendet. Die bisherigen ByteCode-Instruktionen für den Aufruf von Methoden invokevirtual ("normale" Methodenaufrufe), invokestatic (Aufruf statischer Methoden) und invokespecial (Aufruf von Konstruktoren und Superclass-Methoden) verlangen eine genaue Spezifikation der Methoden-Signatur. Die Bytecode-Verifikation während des Classloadings prüft diese ByteCode-Instruktionen und weist Aufrufe, für die es keine zur Signatur passende Methode gibt, zurück. Lediglich die Instruktion invokeinterface (Aufruf einer Methode über einen Interface-Typ, d.h. ohne dass festgelegt wäre, zu welcher Klasse die Methode gehört) war etwas gnädiger bei der Prüfung.All diese Bytecode-Instruktionen sind angelegt für eine statisch geprüfte Sprache wie Java, bei der der Typ jedes Objekts und die gesamte Signatur jeder Methode bereits zur Übersetzungszeit feststeht. Mittlerweile gibt es aber zahlreiche Sprachen auf der Java Virtual Machine, die dynamisch geprüft werden und in denen Methoden eben keine zur Übersetzungszeit festgelegte Signatur haben. Für die Implementierung von dynamischen Sprachen auf der JVM waren deshalb zahlreiche Klimmzüge nötig, um die Methodenaufrufe zu bewerkstelligen. Die neue ByteCode-Instruktion invokedynamic löst diese Probleme.
Java-Entwickler werden in Java 7 noch nicht mit
invokedynamic
nicht
in Berührung kommen, weil der Java-Compiler diese Instruktion bislang
nicht verwendet. Deshalb wollen wir
invokedynamic
an dieser
Stelle nicht näher betrachten. Die neue ByteCode-Instruktion
wird jedoch für die Implementierung der für Java 8 vorgesehenen
Lambdas benutzt werden und dann auch für Java-Programme von Bedeutung
sein.
Concurrency UtilitiesUnter der Bezeichnung "jsr166y" werden Ergänzungen zum Concurrency Support des JDK verstanden. Beschrieben sind die Neuerung im Specification Request JSR 166, den Doug Lea seit Java 5 stetig weiterpflegt. In Java 5 gab es den JSR166, in Java 6 den JSR166x und in Java 7 wird JSR166y hinzukommen (siehe /JSR166y/). Es gibt außerdem noch einen Teil JSR166yextra, der auf Java 8 verschoben wurde, weil er ohne das Sprachmittel der Lambdas nicht gut benutzbar ist. Dabei geht es um Parallel Arrays , d.h. es um die Parallelisierung von Array-Zugriffen.Die wesentliche Neuerung für Java 7 ist ein Framework für die Parallelisierung von rekursiven Aufgaben, Fork/Join Framework genannt. Dabei handelt es sich um einen speziellen Thread-Pool für Tasks, die sich rekursiv in Subtasks zerlegen, diese Subtasks starten, auf die Teilergebnisse warten und daraus ein Gesamtergebnis produzieren. Da solche Aufgaben voneinander abhängen - jede Task wartet auf das Ergebnis ihrer Subtasks – ist der herkömmliche, bereits seit Java 5 im JDK enthaltene Thread-Pool (Klasse ThreadPoolExecutor ) ungeeignet. Er ist für voneinander unabhängige Tasks gedacht. Deshalb gibt es mit der Klasse ForkJoinPool eine Thread-Pool-Implementierung, die für das Abarbeiten rekursiver Aufgaben angelegt ist. Die für Java 8 angekündigten Parallel Arrays werden übrigens auf diesen Fork/Join Framework aufsetzen. Neben dem Fork/Join Framework kommt mit Java 7 die Abstraktionen Phaser zum Package java.util.concurrent hinzu. Der Phaser ist eine flexiblere Variante der seit Java 5 existierenden CyclicBarrier . Während sich an einer CyclicBarrier eine fixe Anzahl von Threads trifft und aufeinander wartet, erlaubt der Phaser eine variable Anzahl von beteiligten Parteien.
Eine weitere Neuerung bei den Concurrency Utilities ist die
TransferQueue
.
Dabei handelt es sich um eine Kombination aus einer normalen
BlockingQueue
und einer
SynchronousQueue
. Bei Bedarf kann der Producer
warten, bis ein Consumer das neue Element abholt (wie bei der
SynchronousQueue
);
alternativ kann er das Element einfach in die Queue legen, ohne auf einen
Abholer zu warten (wie bei der normalen
BlockingQueue
).
InternationalisierungMit Java 7 wird eine Reihe von Modernisierungen im Bereich der Internationalisierung berücksichtigt.
NIO.2Mit "NIO.2" werden Ergänzungen zum Package java.nio bezeichnet. Die "alte" I/O im Package java.io gibt es schon, seit es Java gibt, von kleineren Ergänzungen und Korrekturen einmal abgesehen. Mit Java 1.4 ist neue, d.h. zusätzliche, I/O-Funktionalität hinzugekommen. Dieser Funktionsumfang wurde NIO ("new I/O") genannt und befindet sich in dem Package java.nio. Mit Java 7 kommt nun weitere zusätzliche Funktionalität dazu, die im Java Specification Request (/JSR 203/) beschrieben ist:
Die NIO.2 liefert ein neues, sehr umfangreiches File System API. Dies ersetzt die bisher eher rudimentäre Funktionalität von java.io.File vollständig und geht weit darüber hinaus. Bestandteil ist des Weiteren ein System Provider Interface (SPI), das es ermöglicht, eigene File Systeme (und/oder Sichten auf Geräte) so einzubinden, dass sie über das neue File System API zugreifbar sind. Als Bestandteil von Java 7 wird der System Provider Support für ZIP- und RAR-Archive ausgeliefert.
Der zweite größere Teil der NIO.2 sind Erweiterungen für asynchrone I/O. Dabei geht es zum einen um ein API für asynchrone I/O, das höher angesetzt ist als das bisherige von java.nio.channels.Selector zur Verfügung gestellte API. Zum anderen geht es um die Ausweitung der asynchronen I/O auf Multicast Datagams und File I/O.
Daneben gibt es noch diverse kleinere Ergänzungen, bei denen es um die Unterstützung verschiedener Protokolle und Standards geht. Project JigsawBei "Project Jigsaw" geht es um ein Modulkonzept für Java. Ein bekanntes Defizit von Java ist, dass es keine Module kennt. Man kann heutzutage zwar eine Menge von zusammenhängenden Klassen und Ressourcen z.B. in einer jar-Datei zusammenfassen und hat damit so etwas wie einen Modul, aber es gibt keine Möglichkeit zu beschreiben, was ein Modul anderen Modulen zur Verfügung stellt, was er seinerseits wieder braucht und in welchen Versionen. Das Problem taucht beispielsweise auf, wenn man Software verwendet, die wiederum Software, sagen wir einmal "Apache Commons", verwendet. Wenn nun die verwendete Software unterschiedliche Versionen von Apache Commons braucht, kann man die Commons-Bibliothek aber nur einmal einbinden. In welcher Version soll man das tun? Da nimmt man üblicherweise die jüngste Version der Bibliothek und hofft, dass sie abwärts-kompatibel ist. Wirklich befriedigend ist diese Situation nicht. Was man braucht, ist zumindest eine klare Beschreibung von Export-, Import- und Versionsbeziehungen. Das ist eines der Probleme, das ein Modulkonzept lösen soll.Über die Modularisierung hat es heftige Diskussion gegeben. Sun Microsystems hatte ursprünglich vor, im Rahmen von JSR 294 (Superpackages) und JSR 277 (Java Module System) ein Modulkonzept in Java einzuführen. OSGi (Open Services Gateway initiative - JSR 291) enthält unter anderem auch ein Modulkonzept, dort "Bundle" statt "Module" genannt. Lange und heftige Auseinandersetzung mit der OSGi Fraktion über Kompatibilität bzw. Inkompatibilität, Funktionsumfang, usw. haben am Ende dazu geführt, dass Sun Microsystems die Aktivitäten für JSR 294 und 277 Ende 2008 vorerst eingestellt hat. Stattdessen wurde die Entwicklung eines einfachen Modulkonzepts gestartet, mit dessen Hilfe der JDK selbst modularisiert werden kann. Wenn JDK-Benutzer dieses Modulkonzepts hilfreich finden, können sie es für ihre eigene Software gerne nutzen. Dieses Konzept bzw. seine Implementierung ist "Project Jigsaw" und wird mit Java 8 freigegeben. Type AnnotationsJava 8 wird die sogenannten "Type Annotations" unterstützen. Dabei handelt es sich um eine Änderung an der Sprache, die die Verwendung von Annotationen an deutlich mehr Stellen erlaubt, als es bisher der Fall war. Bislang war die Verwendung von Annotationen im Source Code beschränkt. Es konnten lediglich Packages, Typen, Methoden und Konstruktoren, Felder, lokale Variablen, Methoden-Parameter und Enumeratoren annotiert werden. In Java 8 wird es erlaubt sein, Annotationen überall dort zu verwenden, wo Typen erlaubt sind. Zum Beispiel darf man dann Konstrukte wieMap<@NonNull String, @NonEmpty List<@Readonly Document>> files;schreiben, was bislang syntaktisch unzulässig ist, weil weder zu den Typparametern in generischen Typen noch zum Elementtyp von Arrays Annotationen hinzugefügt werden dürfen. Das Ziel dieser Spracherweiterung ist es, die Annotationen ganz generell als Typ-Qualifikatoren verwenden zu können. Mit Hilfe der Annotationen kann in Java 8 das Typsystem der Sprache Java erweitert werden – ohne die Sprache ändern zu müssen - indem man Typen mit Hilfe von Annotationen näher beschreiben kann. Diese Änderung der Java-Syntax wurde im JSR 308 (siehe /ANNOT/) beschrieben, der zwar bislang nicht formal verabschiedet wurde, aber in Java 8 implementiert werden soll. Wozu braucht man das? Ohne Werkzeuge, die diese neuen Möglichkeiten nutzen, machen die Typ-Annotationen keinen Sinn. Deshalb werden begleitend zu den beschriebenen Sprachänderungen statische Analysewerkzeuge entwickelt, die anhand bestimmter Annotationen Fehler im Source Code aufzuspüren (siehe ebenfalls /ANNOT/). Ein Beispiel für solche Annotationen sind @NonNull und @Nullable . Die betreffenden Werkzeuge sollen verhindern, dass einer @NonNull -Variablen (die nicht null werden darf) der Wert null zugewiesen wird oder dass eine @Nullable -Variable (die den Wert null haben könnte) ohne Prüfung auf != null dereferenziert wird. Diese Werkzeuge werden aber nicht Bestandteil von Java 8 sein, sondern Add-Ons, die man zusätzlich herunterladen und verwenden kann. Project LambdaBeim "Project Lambda" (vormals "Closures") geht es um ein neues Sprachmittel in Java, das aus funktionalen Programmiersprachen stammt. Wenn man heutzutage in Java eine Funktionalität formulieren und als Parameter übergeben möchte, dann muss man ein Interface definieren und eine Klasse, die das Interface implementiert. Beispiel: Wenn man eine Funktionalität asynchron in einem anderen Thread ausführen will, muss man eine Klasse schreiben, die das Interface Runnable mit seiner run() -Methode implementiert, in der run() -Methode wird die eigentliche Funktionalität formuliert, dann wird ein Objekt von neuen Typ alloziert und einem Thread oder Thread-Pool zur Ausführung übergeben. Eigentlich geht es aber nur um das, was die run() -Methode tut. Der syntaktische Überbau für das Runnable-Interface, die implementierende Klasse und die Objekt-Konstruktion ist eigentlich komplett überflüssig. Ähnliche Situationen findet man bei der Implementierung von Callbacks oder Listener-Interfaces oder ganz allgemein bei Interfaces mit nur einer Methode.Um die Syntax zu vereinfachen, soll es Lambda-Ausdrücke geben. Anstelle von new Thread(new Runnable { public void run() { System.out.println (“Hello World!”); } }).start();würde man lediglich sagen new Thread( #{ System.out.println (“Hello World!”) ).start();Der mit "#" eingeleitete Ausdruck wäre das Lambda und beschreibt nur noch das Wesentliche, nämlich die Funktionalität. Das ist eine sehr vereinfachte Darstellung von Lambdas. Im Zusammenhang mit diesem neuen Sprachmittel ist noch weit mehr diskutiert worden und es wird auch noch immer diskutiert über die Syntax und die Mächtigkeit des Sprachmittels. Inspiriert sind die Lambdas von entsprechenden Konstrukten in funktionalen Programmiersprachen, die insbesondere durch neue hybride Sprachen wie Scala und Skriptsprachen wie Groovy populär geworden sind. Das Sprachmittel der Lambdas ist in den Jahren 2006 bis 2008 sehr heftig diskutiert worden und es gab gleich drei konkurrierende Vorschläge dafür (siehe /CLDE/), damals noch unter der Bezeichnung "Closures". Wegen des kontroversen Ansatzes der verschiedenen Vorschläge stagnierte das Thema für mehr als ein Jahr und es sah zunächst so aus, als wären Lambdas/Closures für Java gar kein Thema mehr. Im November 2009 wurde die Idee wieder aufgegriffen und in Java 8 sollen Lambdas dann verfügbar sein (siehe /BGOEL/).
Lambda-Ausdrücke werden u.a. für die ParallelArrays gebraucht,
die ebenfalls mit Java 8 freigegeben werden sollen. Die ParallelArrays
sind ein Framework, dem man nur noch sagen muss, welche Funktionalität
auf jedes einzelne Array-Element angewandt werden soll und der dann für
die parallele Ausführung sorgt. Die Lambdas würden die
Benutzung der ParallelArrays drastisch vereinfachen, denn den syntaktischen
Überbau für die Beschreibung der Funktionalität in Form
von Interfaces und implementierenden Klassen könnte man mit Lambdas
komplett eliminieren.
Zusammenfassung und AusblickIn diesem Beitrag haben wir eine Übersicht über die neuen Sprachmittel und JDK-Erweiterungen gegeben, die mit Java 7 und Java 8 zu erwarten sind. In den folgenden Beiträgen werden wir einige der Neuerungen näher diskutierenLiteraturverweise
Die gesamte Serie über Java 7:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
© Copyright 1995-2013 by Angelika Langer. All Rights Reserved. URL: < http://www.AngelikaLanger.com/Articles/EffectiveJava/57.Java7.Overview/57.Java7.Overview.html> last update: 24 Jan 2013 |