http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u2-download-1377129.html. Der Blog-Eintrag http://blogs.oracle.com/darcy/entry/project_coin_7u2_fixes gibt zwei Beispiele für Fehler aus den neuen Sprachfeatures, die gefixt sind.
NetBeans 7.1 Code-Transformation nach Java 7
Wähle im Menü Refactor > Inspect and Transform … und dann im Dialog bei Use:/Configuration: den Eintrag Convert to Java 7 aus. Ein Klick auf Inspect startet die Suche und listet Änderungsmöglichkeiten auf und bietet an, die Stellen automatisch zu beheben.
Ich habe das Tool auf den Beispielen meines Buches angewendet und die meisten Hinweise beziehen sich auf Diamond und natürlich im IO-Kapitel auf auf try-mit-Ressourcen. Damit habe ich heute den ganzen Tag verbracht und auch noch ein paar kleine Fehler gefunden. Eine Stelle ist interessant:
XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter( new FileOutputStream( "writenParty.xml" ) );
XMLStreamWriter hat close() aber kein AutoCloseable. Kann man als Fehler ansehen.
Das hier formt der Konverter nicht um, er beginnt erst bei “fett” mit dem switch, das liegt am zweiten if, was nicht als if else formuliert ist.
if ( "Ende".equals(e.getActionCommand()) )
System.exit( 0 );
if ( "fett".equals(e.getActionCommand()) )
t.setFont( font = font.deriveFont( font.getStyle() ^ Font.BOLD ) );
else if ( "kursiv".equals(e.getActionCommand()) )
t.setFont( font = font.deriveFont( font.getStyle() ^ Font.ITALIC ) );
Inselupdate: Vererbung und Überschattung von statischen Variablen
Die Konstanten einer Schnittstelle können einer anderen Schnittstelle vererbt werden. Dabei gibt es einige kleine Einschränkungen. Wir wollen an einem Beispiel sehen, wie sich die Vererbung auswirkt, wenn gleiche Bezeichner in den Unterschnittstellen erneut verwendet werden. Als Basis unseres Beispiels steht eine Schnittstelle BaseColors mit ein paar Deklarationen von Farben. Zwei Unterschnittstellen erweiterten BaseColor, einmal CarColors und PlaneColors, die für Farbdeklarationen für Autos und Flugzeuge stehen. Eine besondere Schnittstelle FlyingCarColors erweitert die beiden Schnittstelen CarColors und PlaneColors, denn es gibt auch fliegende Autos, die eine Farbe haben können.
interface BaseColors
{int WHITE = 0;
int BLACK = 1;
int GREY = 2;
}interface CarColors extends BaseColors{int WHITE = 1;
int BLACK = 0;
}interface PlaneColors extends BaseColors{int WHITE = 0;
int GREY = 2;
}interface FlyingCarColors extends CarColors, PlaneColors{}public class Colors{public static void main( String[] args ){System.out.println( BaseColors.GREY ); // 2
System.out.println( CarColors.GREY ); // 2
System.out.println( BaseColors.BLACK ); // 1
System.out.println( CarColors.BLACK ); // 0
System.out.println( PlaneColors.BLACK ); // 1
System.out.println( FlyingCarColors.WHITE );// The field FlyingCarColors.WHITE is ambiguous
System.out.println( FlyingCarColors.GREY ); // The field FlyingCarColors.GREY is ambiguous
}}Die erste wichtige Tatsache ist, dass unsere drei Schnittstellen ohne Fehler übersetzt werden können, aber nicht die Klasse Colors. Das Programm und der Compiler zeigen folgendes Verhalten:
- Schnittstellen vererben ihre Eigenschaften an die Unterschnittstellen. CarColors und auch PlaneColors erbten die Farbe WHITE, BLACK und GREY aus BaseColors.
- Konstanten dürfen überschattet werden. CarColors vertauscht die Farbdeklarationen von WHITE und BLACK und gibt ihnen neue Werte. Wird jetzt der Wert CarColors.BLACK verlangt, liefert die Umgebung den Wert 0, während CarColors.BLACK 1 ergibt. Auch PlaneColor überdeckt die Konstanten WHITE und GREY obwohl sie Farbe mit dem gleichen Wert belegt sind.
- Erbt eine Schnittstelle von mehreren Oberschnittstellen, so ist es zulässig, wenn die Oberschnittstellen jeweils ein gleichlautendes Attribut haben. So erbt etwa FlyingCarColors von CarColors und PlaneColors den Eintrag WHITE, BLACK und GREY.
- Unterschnittstellen können aus zwei Oberschnittstellen die Attribute gleichen Namens übernehmen, auch wenn sie einen unterschiedlichen Wert haben. Das testet der Compiler nicht. FlyingCarColors bekommt aus CarColors ein WHITE mit 1 aber aus PlaneColors das Weiß mit 0. Daher ist auch der Zugriff FlyingCarColors.WHITE in dem Beispiel Colors auch nicht möglich und führt zu einem Compilerfehler. Bei der Benutzung muss ein unmissverständlicher qualifizierter Name verwendet werden, der deutlich macht, welches Attribut gemeint ist, also zum Beispiel CarColors.WHITE oder PlaneColors.WHITE. Ähnliches gilt für die Farbe GREY. Obwohl Grau durch die ursprüngliche Deklaration bei BaseColor und auch bei der Überschattung in PlaneColors immer Zwei ist, ist die Nutzung durch FlyingCarColors.GREY nicht zulässig. Das ist ein guter Schutz gegen Fehler, denn wenn der Compiler dies durchließe, könnte sich im Nachhinein die Belegung von GREY in BaseColors oder PlaneColors ohne Neuübersetzung aller Klassen ändern, und zu Schwierigkeiten führen. Diesen Fehler – die Oberschnittstellen haben für eine Konstante unterschiedliche Werte – müsste die Laufzeitumgebung erkennen. Doch das ist nicht möglich und in der Regel setzt der Compiler die Werte auch direkt in die Aufrufstelle ein und ein Zugriff auf die Konstantenwerte der Schnittstelle findet nicht mehr statt.
Google Guava 11
Neues unter http://code.google.com/p/guava-libraries/wiki/Release11, genauer http://docs.guava-libraries.googlecode.com/git-history/v11.0/jdiff/changes.html. 2 neue Pakete sind:
- http://docs.guava-libraries.googlecode.com/git-history/v11.0/javadoc/com/google/common/hash/package-summary.html und
- http://docs.guava-libraries.googlecode.com/git-history/v11.0/javadoc/com/google/common/math/package-summary.html
Mit der neuen MathInt Klasse beschäftigt sich ausführlicher der Blogpost http://marxsoftware.blogspot.com/2011/12/guava-release-11s-intmath.html.
NetBeans 7.1 ist raus
Guava AppendableWriter (internal class) and CharStream.asWriter()
With the current version the class is now package visible! If you want to use the class, copy it in your project and make it public. Or make use of CharStream.asWriter().
The classes StringWriter, CharArrayWriter and ByteArrayOutputStream have two things in common: a) They are sinks and when you write into them you ask these classes for the collected result; b) the internal buffer always starts empty. So for getting the result the classes offer different methods:
- StringWriter: toString() return the buffer’s current value as a string.
- CharArrayWriter: toCharArray() returns a copy of the input data as a char array; toString() returns the input data as a String.
- ByteArrayOutputStream: toByteArray() returns a newly allocated byte array with a copy of the stream data. toString(String enc) converts the buffer’s contents into a String object, translating bytes into characters according to the given character encoding. The parameter less methode toString() uses the default encoding.
One can see the second point, that every of these sink classes starts with an empty buffer, as a disadvantage. If one wants to append to an existing String or char or byte array this has to be done in a second step. It would be nice to have a class, lets say StringBuilderWriter, which writes into a mutable StringBuilder. But Java SE doesn’t offer such a class.
The Google Collection library provides a class AppendableWriter which writes into an Appendable. The Appendable interface was introduced in Java 5 and is implemented by classes to whom you can append chars or Strings to. It dictates three methods:
- Appendable append(char c)
- Appendable append(CharSequence csq)
- Appendable append(CharSequence csq, int start, int end)
Implementing classes are among others:
- StringBuilder, StringBuffer
- Every Writer-class; the base class implements Appendable (this was retrofitted in Java 5)
So to write into a StringBuilder all you have to do is:
StringBuilder sb = new StringBuilder( "start-" );Writer w = new AppendableWriter( sb );
w.write( "middle" );
w.close();sb.append( "-end" );
System.out.println( sb ); // start-middle-end
So with AppendableWriter its easy to represent every Appendable as a Writer. This is exactly what the static method asWriter() in the utility class CharStreams does:
public static Writer asWriter(Appendable target) {if (target instanceof Writer) {return (Writer) target;
}return new AppendableWriter(target);}If the Appendable is already of subtype Writer it does not make sense to wrap it in an AppendableWriter again, so the target is directly returned. But what happens if you call close() or flush() on this special Writer—an Appendable doesn’t have close() neither flush()? The answer is simple: If you call close()/flush() on an AppendableWriter the implementation checks if the constructor argument implements Closeable/Flushable and calls close()/flush() accordingly. That means if you close/flush this Writer the close()/flush() operation will be delegated otherwise—for example in the case of StringBuilder with does neither implement Closeable nor Flushable—nothing happens.
Warum IntelliJ einfach g*eil ist
(Passend zur Meldung, das Findbugs in Version 2.0 ist)
FindBugs 2 ist da
Nach dem auf der Mailingliste schon seit längerem eine Version 2 angekündigt wurde, mussten Entwickler doch noch längere Zeit warten. Jetzt ist es soweit. Infos unter http://findbugs.sourceforge.net/findbugs2.html und http://code.google.com/p/findbugs/w/list.
Die Version 2 kann man gleich über JNLP mit ein paar Sourcen ausprobieren:
Im JDK finden sich immer noch einige Fehler, toll, was FindBugs so findet. Das hier zum Beispiel:
- if (name != null || name.length > 0). Ist name == null, wird name.length zu einer NPE führen. Hier muss ein && statt ||.
oder
- if (lookbehind.length() == 1) {
char c0 = (lookbehind == null) ? ‚|‘ : lookbehind.charAt(0);
oder
- if (!wellformed){
if (!wellformed){
oder
if ((parent instanceof LiteralElement) ||
(parent instanceof LiteralElement)) {
oder
- boolean isInitValueValid(int v) {
if ((v < 0) || (v > SnmpUnsignedInt.MAX_VALUE)) {
COOL!
InfoQ Interview über Spring 3.1 und Java 7
Nächste Runde bei IntelliJ: Version 11
News auf http://www.jetbrains.com/idea/whatsnew/.
Spring Update auf Version 3.1
Features wie auf http://www.springsource.org/node/3334 genannt:
- Comprehensive Java-based application configuration
- New caching abstraction
- Environment support, including bean definition profiles and hierarchical property source management
- Support for Hibernate 4
- Java 7 fork/join and JDBC 4.1 support
Hibernate in Version 4
Download wie üblich unter http://www.hibernate.org/. News im Blog (http://in.relation.to/Bloggers/HibernateCore40IsFinal), gerade offline…
Erster Draft von JSR-335 (Lambda) verfügbar + Devoxx Folien
Siehe http://mail.openjdk.java.net/pipermail/lambda-dev/2011-November/004191.html bzw. http://jcp.org/en/jsr/detail?id=335.
Folien zur aktuellen Lambda-Version von der Konferenz sind hier: http://blogs.oracle.com/briangoetz/resource/devoxx-lang-lib-vm-co-evol.pdf.
Der aktuelle Compiler weist aber noch Unterschiede auf, sie werden hier diskutiert: http://mail.openjdk.java.net/pipermail/lambda-dev/2011-November/004253.html.
Ergebnisse “JDK8 Warnings Cleanup Day”
In den Dokus bzw. im Code sind immer wieder kleine Bugs und Warnings, die leicht behoben werden können. Daher lief am 1. Dez. ein Cleanup Day: http://mail.openjdk.java.net/pipermail/jdk8-dev/2011-December/000380.html, http://wikis.sun.com/display/OpenJDK/JDK8+Warnings+Cleanup+Day. In der Mailingliste werden die Bugs besprochen und es ist ganz interessant, was da rausgekommen ist.
Flex geht zu Apache, das ist dann wohl das Aus
Adobe kündigte dies in http://blogs.adobe.com/flex/2011/11/your-questions-about-flex.html an. Damit ist klar: HTML 5 is the way to go. Flex war ein Nischenprodukt und der Wechsel zum Friedhof Apache wird das nicht ändern. Tschüss zur nächsten Client-Technologie.
Google Plugin für Eclipse ist nun quelloffen
Mehr Details unter http://googlewebtoolkit.blogspot.com/2011/11/google-plugin-for-eclipse-gpe-is-now.html. Was das für Konsequenzen hat, muss sich aber erst noch zeigen.
Java 8 Binary Preview mit Lambda Unterstützung
Siehe http://jdk8.java.net/lambda/. Dort gibt es den Download.
JEP für Lambda und Extension Methods
JEPs sind die neuen JSRs. Somit gibt es auch für die Java 8-Neuerungen ein JEP: http://openjdk.java.net/jeps/126. Eine Spezifikation ist das jedoch nicht, nur eine “Aufruf” für eine Neuerung oder Änderung.