http://www.tutego.de/java/jdk7-Java-SE-7.htm
Fehlt was?
http://www.tutego.de/java/jdk7-Java-SE-7.htm
Fehlt was?
http://jdk7.java.net/download.html
Änderungen:
http://hg.openjdk.java.net/jdk7u/jdk7u/ws-b02-2011-08-12_39
|
Changeset |
Bug ID |
Synopsys |
|
can’t generate api docs for JDK7 updates |
http://hg.openjdk.java.net/jdk7u/jdk7u/jdk
|
Changeset |
Bug ID |
Synopsys |
|
klist does not detect non-existing keytab |
||
|
Splash screen is not shown in 64-bit Linux with 16-bit color depth |
||
|
java -help still shows http://java.sun.com/javase/reference |
||
|
(launcher) java -jar throws NPE if JAR file does not contain Main-Class attribute |
||
|
PPC: NIO: java.io.IOException: Invalid argument in sun.nio.ch.FileDispatcherImpl.read0 |
http://hg.openjdk.java.net/jdk7u/jdk7u/langtools
|
Changeset |
Bug ID |
Synopsys |
|
Attr.PostAttrAnalyzer misses a case |
||
|
Proposed javac argument processing performance improvement |
||
|
(javac) allow enabling or disabling of String folding |
||
|
(javadoc) improve performance on accessing inlinedTags |
||
|
StringIndexOutOfBoundsException for empty @serialField tag |
||
|
(javadoc) promote method visibility for netbeans usage |
Den Szene-Graph über Java Programmcode aufzubauen ist eine Möglichkeit, doch JavaFX erlaubt es auch, die Objekte über XML zu konfigurieren. Das erlaubt es viel einfacher, grafische Oberflächen über Gui-Builder aufzubauen und sauber das Layout (was) vom Code (wie) zu trennen.
Die hierarchische Struktur von XML passt natürlich prima zu der Hierarchie, die es bei grafischen Oberflächen gibt: Ein Fenster enthält Container, die wiederum Elemente enthalten, usw. Für unser kleines Beispiel soll eine Oberfläche drei Elemente bieten: Eine Beschriftung, ein Textfeld und eine Schaltfläche. Drückt der Anwender die Schaltfläche, soll der Text im Textfeld in Großbuchstaben konvertiert werden.
Die XML-Datei covert2UpperCase.fxml sieht so aus:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.layout.*?> <?import javafx.scene.control.*?> <HBox xmlns:fx="http://javafx.com/fxml" fx:controller="com.tutego.insel.javafx.ButtonController"> <children> <Label text="Eingabe: " /> <TextField fx:id="input" /> <Button text="Konvertiere" onAction="#convertAction" /> </children> </HBox>
Die Hierarchie ist gut zu erkennen. Die interessanten Dinge sind andere:
Die Ereignisbehandlung ist komplett aus der FXML-Datei rausgezogen und wandert in Controller-Klassen. Die eigene Klasse ButtonController, die voll qualifiziert bei fx:controller genannt wurde, enthält:
com/tutego/insel/javafx/ButtonController.java
package com.tutego.insel.javafx; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.TextField; public class ButtonController { @FXML private TextField input; @FXML protected void convertAction( ActionEvent event ) { input.setText( input.getText().trim().toUpperCase() ); } }
Drei Dinge fallen ins Auge:
Das Hauptprogramm ist nun relativ einfach:
com/tutego/insel/javafx/FXMLDemo.java, start()
@Override public void start( Stage stage ) throws Exception { Parent p = FXMLLoader.load( getClass().getResource( "covert2UpperCase.fxml" ) ); stage.setScene( new Scene( new Group( p ), 500, 400 ) ); stage.setVisible( true ); }
Was noch alles mit FXML möglich ist, beschreibt ein Dokument von Oracle: http://fxexperience.com/wp-content/uploads/2011/08/Introducing-FXML.pdf.
Änderungen: Kein Zip mehr zum Auspacken, sondern eine exe. Keine Demos mehr dabei. APIs ändern sich, viele Beispiele muss ich anpassen. Bei einer Beta ist das natürlich OK, dennoch überlege ich mir, ob ich JavaFX unter diesen Umständen überhaupt in die Insel setzen kann. An großen FX-Apps kann man so nicht denken, die Änderungen machen einen verrückt.
Das folgende Code für mein Semaphoren-Beispiel (http://openbook.galileodesign.de/javainsel7/javainsel_10_006.htm) habe ich vereinfacht und ist so nicht wirklich korrekt:
1: static Runnable r = new Runnable() {2: public void run() {3: while ( true ) {4: try5: {6: semaphore.acquire();7:8: System.out.println( "Thread=" + Thread.currentThread().getName() +9: ", Available Permits=" + semaphore.availablePermits() );10: Thread.sleep( 2000 );11: }12: catch ( InterruptedException e ) {13: e.printStackTrace();14: }15: finally {16: semaphore.release();17: }18: }19: }20: };Wer findet den Fehler noch?
Nun, in der 10. Auflage ist der Fehler jedenfalls korrigiert und ein Dank geht an Marco Völz.
Durch Zufall bin ich bei Heise über http://www.heise.de/developer/artikel/Von-C-nach-Java-Teil-2-Files-I-O-und-eine-Entwicklungsumgebung-1326652.html gestoßen. Eine Implementierung stößt mir auf:
public CFind(String s) throws Exception {
super(s);
if (!isDirectory()) throw new Exception(s+" is NOT a directory!");
for (File f:listFiles()) {
if (f.isDirectory()) {
System.out.println(f.getAbsolutePath());
new CFind(f.getAbsolutePath());
}
}
Es ist keine gute Idee eine direkte Instanz von Exception zu bauen aus auszulösen. Wenn, sollten es immer Unterklasse von Exception sein. In diesem Fall ist das Argument falsch, sodass man ein IllegarArgumentException auslösen könnte. Als zweites gilt throws Exception in der Methodensignatur zu vermeiden – das zwingt Nutzer zur catch(Exception e)-Keule, ganz schlecht, weil dann auch alle RuntimeExceptions aufgefangen werden.
In der c’t hat Michael Tamm in der Ausgabe 17 (August) einen Beitrag über Java 7 geschrieben. Der ist ganz gut gelungen und gibt einen netten Einblick in die Neuerungen von Java 7 (präzisiertes rethrow hat er irgendwie verschwiegen, weiß nicht warum).
Ein paar Kleinigkeiten kann man noch anfügen:
Die beschriebenen Dinge sind nur missverständlich, aber leider gibt es auch zwei dickere Falschaussagen:
Ein Video erklärt die Web-Anwendung (sehr ungewöhnlich für so ein Tool)
d
Live-Demo unter http://xplrarc.massey.ac.nz/index.jsp.
Siehe http://googleappengine.blogspot.com/2011/08/app-engine-153-sdk-released.html, http://code.google.com/p/googleappengine/wiki/SdkForJavaReleaseNotes:
- Blobstore API – We’ve removed the limits on the size of blob uploads. You can now upload files of any size, allowing your app to serve images, video, or anything your internet connection can handle.
- Index retrieval – We’ve added the ability for you to programmatically retrieve the list of indexes you’ve currently defined in the datastore, as well as their statuses.
- Datastore Admin – You can now enable the Datastore Admin function from the Admin Console. This will allow Java users to make use of this functionality, like deleting all entities of a certain kind, without having to upload a Python version of their application. And for Python developers, you no longer need to enable this in your app.yaml file.
- HRD Migration Trusted Testers – We are seeking early adopters to try out an improved HRD migration tool that requires a read-only period relative to your datastore write rate (as opposed to your datastore size, which is how the current version behaves). Please see the release notes for more information.
- Download app – Using the AppCfg download_app command, you can download any files that were uploaded from your war directory when you last updated the app version.
Schaut euch
an.
Interessant für Anwender mobiler Endgeräte, die kein Swing können (Android) oder dürfen (iPad).
Die HTML-Anwendung besteht aus einem bisschen JavaScript, die Interaktionen zum Server schickt, also Mausklicks, Tastendrücke, usw. Dabei entstehen Events wie
MM_984_567_MM_986_567_
die an http://icedrobot.de:9091/EventReceiver per POST gesendet werden. Die Swing-Anwendung (die werden dafür richtig viel Speicher brauchen denke ich, das kommt vielleicht noch mal raus…) läuft nur auf dem Server und der reagiert mit geänderten Bildschirmausschnitten, die wieder auf den Brower Canvas gezeichnet werden. Ist so wie ein remote VNC-Server (http://code.google.com/p/jsvnc/), schöne Sache das. HTML5 wir lieben dich ![]()
“Schön” im Sourcecode der Kommentar:
//Exclude WebKit for now, as it will trigger a memory leak.
//TODO: should be version dependent, as its fixed in Chrome 14
Ich habe noch Einladungen bei Google+: https://plus.google.com/_/notifications/ngemlink?path=%2F%3Fgpinv%3Dk4jYjYo4HX4%3AYOvNkIeCnKA. Selbst habe ich ein Profil unter https://profiles.google.com/ullenboom, wer möchte, kann mich gerne hinzufügen, aber ich weiß noch nicht so genau, was ich dort schreiben werde. Die Java-Sachen bleiben auf dem Blog.
Die News unter http://www.jidesoft.com/company/news.htm. Neu unter anderem:


Sehr interessant finde ich den (mutigen?) Schritt:
This means we will now officially stop supporting JDK5.
Die Komponentensammlung kostet Geld, frei ist http://www.jidesoft.com/products/oss.htm.
Attila Furdek ist Mathelehrer und hat ein interessantes Buch veröffentlicht: http://www.amazon.de/Fehler-Beschw%C3%B6rer-Typische-Fehler-L%C3%B6sen-Mathematikaufgaben/dp/3831121109 (http://www.bod.de/index.php?id=296&objk_id=51857). Ich finde den Ansatz toll: Er stellt eine Aufgabe vor und suggeriert richtige Lösungen, die aber falsch sind. (Bei Amazon kann man sich ein paar Sachen anschauen.) Der Lernende muss zeigen, warum der Lösungsweg falsch ist. Mit gefällt die Idee gut. In meinen Java-Kursen mache ich am Anfang etwas ähnliches: ich gebe syntaktisch falschen Programmcode vor (Klammern fehlen, Variablendeklarationen fehlen, Initialisierungen fehlen, Semikolon fehlt, usw.), und die Lernenden müssen ohne Compilermeldungen die Fehler finden. Wer die meisten Fehler findet, ist Bug-König. Danach wird aufgelöst und die die Fehler mit dem Compiler abgeglichen, um die Meldungen des Compilers zu lernen und mit den Fehlertypen in Verbindung zu bringen.
Der “Trick”: Es gibt nicht nur einen “Next”-Zeiger, sondern einen “Aux”-Zeiger, der auf alle möglichen “Next”-Knoten zeigen kann. Der Hammer… Details: http://www.google.com/patents/about?id=26aJAAAAEBAJ.
Oftmals ist das Ordnungskriterium aus mehreren Bedingungen zusammengesetzt, wie die Sortierung in einem Telefonbuch zeigt. Erst gibt es eine Sortierung nach dem Nachnamen, dann folgt der Vorname. Um diese mit einem Compartor-Objekt zu lösen, müssen entweder alle Einzelvergleiche in ein neues Compartor-Objekt verpackt werden, oder einzelne Comparatoren zu einem „Super“-Comparator zusammengebunden werden – die zweite Lösung ist natürlich schöner, denn das erhöht die Wiederverwendbarkeit, denn einzelne Comparatoren können dann leicht für andere Zusammenhänge genutzt werden.
Comparatoren in eine Vergleichskette setzen
Am Anfang steht ein besonderer Comparator, der sich aus mehreren Comparatoren zusammensetzt. Immer dann, wenn ein Teil-Compartor bei zwei Objekten aussagt, dass sie gleich sind (der Vergleich liefert 0 ist), so soll der nächste Comparator die Endscheidung fällen – kann er das auch nicht, weil das Ergebnis wieder 0 ist, geht es zum nächsten Vergleicher.
Den Programmcode wollen wir einen neue Hilfsklasse ComparatorChain setzen:
package com.tutego.insel.util; import java.util.*; /** * A {@link Comparator} that puts one or more {@code Comparator}s in a sequence. * If a {@code Comparator} returns zero the next {@code Comparator} is taken. */ public class ComparatorChain<E> implements Comparator<E> { private List<Comparator<E>> comparatorChain = new ArrayList<Comparator<E>>(); /** * Construct a new comparator chain from the given {@code Comparator}s. * The argument is not allowed to be {@code null}. * @param comparators Sequence of {@code Comparator}s */ @SafeVarargs // ab Java 7 public ComparatorChain( Comparator<E>... comparators ) { if ( comparators == null ) throw new IllegalArgumentException( "Argument is not allowed to be null" ); Collections.addAll( comparatorChain, comparators ); } /** * Adds a {@link Comparator} to the end of the chain. * The argument is not allowed to be {@code null}. * @param comparator {@code Comparator} to add */ public void addComparator( Comparator<E> comparator ) { if ( comparator == null ) throw new IllegalArgumentException( "Argument is not allowed to be null" ); comparatorChain.add( comparator ); } /** * {@inheritDoc} */ @Override public int compare( E o1, E o2 ) { if ( comparatorChain.isEmpty() ) throw new UnsupportedOperationException( "Unable to compare without a Comparator in the chain" ); for ( Comparator<E> comparator : comparatorChain ) { int order = comparator.compare( o1, o2 ); if ( order != 0 ) return order; } return 0; } }
Die ComparatorChain können wir auf zwei Weisen mit den Comparator-Gliedern füttern: einmal zu Initialisierungszeit im Konstruktor, und dann später noch über die addComparator()-Methode. Beim Weg über den Konstruktor ist ab Java 7 die Annotation @SafeVarargs zu nutzen, da sonst die Kombination eines Varargs und Generics auf der Nutzerseite zu einer Warnung führt.
Ist kein Comparator intern in der Liste, wird das compare() eine Ausnahme auslösen. Der erste Comparator in der Liste ist auch das Vergleichsobjekt was zuerst gefragt wird. Liefert er ein Ergebnis ungleich 0 liefert das die Rückgabe der compare()-Methode. Ein Ergebnis gleich 0 führt zur Anfrage des nächstes Comparators in der Liste.
Wir wollen diese ComparatorChain für ein Beispiel nutzen, dass eine Liste nach Nach- und Vornamen sortiert.
package com.tutego.insel.util; import java.util.*; public class ComparatorChainDemo { public static class Person { public String firstname, lastname; public Person( String firstname, String lastname ) { this.firstname = firstname; this.lastname = lastname; } @Override public String toString() { return firstname + " " + lastname; } } public final static Comparator<Person> PERSON_FIRSTNAME_COMPARATOR = new Comparator<Person>() { @Override public int compare( Person p1, Person p2 ) { return p1.firstname.compareTo( p2.firstname ); } }; public final static Comparator<Person> PERSON_LASTNAME_COMPARATOR = new Comparator<Person>() { @Override public int compare( Person p1, Person p2 ) { return p1.lastname.compareTo( p2.lastname ); } }; public static void main( String[] args ) { List<Person> persons = Arrays.asList( new Person( "Onkel", "Ogar" ), new Person( "Olga", "Ogar" ), new Person( "Peter", "Lustig" ), new Person( "Lara", "Lustig" ) ); Collections.sort( persons, PERSON_LASTNAME_COMPARATOR ); System.out.println( persons ); Collections.sort( persons, PERSON_FIRSTNAME_COMPARATOR ); System.out.println( persons ); Collections.sort( persons, new ComparatorChain<Person>( PERSON_LASTNAME_COMPARATOR, PERSON_FIRSTNAME_COMPARATOR ) ); System.out.println( persons ); } }
Die Ausgabe ist:
[Peter Lustig, Lara Lustig, Onkel Ogar, Olga Ogar]
[Lara Lustig, Olga Ogar, Onkel Ogar, Peter Lustig]
[Lara Lustig, Peter Lustig, Olga Ogar, Onkel Ogar]
package insel;
public class Insel {
public static void main(String[] args) {
switch (1) {
case (1):
}
switch ("") {
case (""):
}
}
}
Eclipse und NetBeans kommen damit zurecht, nicht aber javac. Der Fehler ist bekannt und für das nächste Update gefixt.
An exception has occurred in the compiler (1.7.0). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.NullPointerException
at com.sun.tools.javac.comp.Lower.visitStringSwitch(Lower.java:3456)
at com.sun.tools.javac.comp.Lower.visitSwitch(Lower.java:3357)
at com.sun.tools.javac.tree.JCTree$JCSwitch.accept(JCTree.java:959)
at com.sun.tools.javac.tree.TreeTranslator.translate(TreeTranslator.java:58)
at com.sun.tools.javac.comp.Lower.translate(Lower.java:2160)
…
Download unter http://download.eclipse.org/eclipse/downloads/drops/S-3.8M1-201108031800/index.php (Windows), die News unter http://www.eclipse.org/jdt/ui/r3_8/Java7news/whats-new-java-7.html. Na endlich muss ich kein NetBeans mehr nutzen
. Interessant ist auch zur Einführung vom Diamanten

aber es fehlt noch eine “Clean”, um das automatisch zu konvertieren.
Um zu testen, wie sich die neue NIO.2-Bibliothek so in der Praxis macht, habe ich unsere tutego-Software auf NIO.2 gebracht. Als erstes habe ich File durch Path/Paths/Files-Aufrufe ersetzt. Dabei sind mir schon ein paar Stellen aufgefallen, die ich gerne noch verbessert sehen würde für >= Java 8.