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.
Autor: Christian Ullenboom
Ein dämliches Patent: Verallgemeinerte verkettete Listen
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.
Aneinanderreihung von Comparatoren
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]
Bug des Tages im Java-Compiler: case
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)
…
Eclipse 3.8M1 (mit funktionierendem Java 7 Support)
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.
NIO.2 Umstellung. Mein Fazit (nach einem Tag)
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.
- Von den File-Konstrukturen gibt es: File(File parent, String child) und File(String parent, String child). Es ist praktisch, dass der erste Teil entweder File oder String sein kann. Ich habe bei mir eine Menge von Aufrufen der Art new File(path, filename). Mal ist path ein String, mal ein File (in der Regel File). Bei der Konvertierung zu Path wird es ungemütlich, denn es gibt nur get(String first, String… more) aber kein get(Path first, String… more). Also läuft es auf ein path.resove(child) raus, was ich aber nicht so schön finde wie ein get(path, child). Aber alles Geschmacksache.
- File wird öfter als Parametertyp akzeptiert als Path. So muss ich schreiben:
PrintWriter out = new PrintWriter( testimonalsPath.toFile() );
Schöner wäre ein Konstruktur PrintWriter(Path). - Die Methode getFileName() liefert keinen String, sondern ein Path-Objekt nur mit dem Dateinamen. Daher führt folgendes nicht zum Ziel: path.getFileName().endsWith(".xml"). Und path.getFileName().toString()endsWith(".xml") ist etwas lang.
- Files.readAllBytes() ist zwar schön, aber Files.readAllChars(Path,CharSet) wäre auch nett.
Hintergründe zum Java 7 Bug
http://blog.thetaphi.de/2011/07/real-story-behind-java-7-ga-bugs.html. Meine Empfehlung: Bis zum ersten Update warten und Java 7 nicht produktiv einsetzen.
Joda Time 2.0 ist raus
News unter http://joda-time.sourceforge.net/upgradeto200.html. Es gibt Brüche in der API!
JavaFX Update und deklarative UIs
JavaFX führt in der aktuellen Version eine deklarative Beschreibung für Oberflächen auf der Basis von XML ein. Die Elemente und Namensräume können sich noch ändern, aber einen ersten Einblick gibt http://fxexperience.com/2011/07/introducing-fxml/.
Inselupdate: Ein Wort zu Microsoft, Java und zu J++, J#
In der Anfangszeit verursachte Microsoft einigen Wirbel um Java. Mit Visual J++ (gesprochen „Jay Plus Plus“) bot Microsoft schon früh einen eigenen Java-Compiler (Teil vom Microsoft Development Kit) und mit der Microsoft Java Virtual Machine (MSJVM) eine eigene schnelle Laufzeitumgebung. Das Problem war nur, dass Dinge wie RMI und JNI am absichtlich fehlten[1] – JNI wurde 1998 nachgereicht. Entgegen alle Standards führte der J++-Compiler neue Schlüsselwörter multicast und delegate ein. Weiterhin fügte Microsoft einige neue Methoden und Eigenschaften hinzu, zum Beispiel J/Direct, um der plattformunabhängigen Programmiersprache den Windows-Stempel zu verpassen. Mit J/Direct konnten Programmierer aus Java heraus direkt auf Funktionen aus dem Win32-API zugreifen und damit reine Windows-Programme in Java programmieren. Durch Integration von DirectX soll die Internet-Programmiersprache Java multimediafähig gemacht werden. Das führte natürlich zu dem Problem, dass Applikationen, die mit J++ erstellt wurden, nicht zwangsläufig auf anderen Plattformen lauffähig sind waren. Sun klagte gegen Microsoft.
Da es Sun in der Vergangenheit finanziell nicht besonders gut ging, pumpte Microsoft im April 2004 satte 1,6 Milliarden US$ in die Firma. Microsoft erkaufte sich damit das Ende der Kartellprobleme und Patentstreitigkeiten. Dass es bis zu dieser Einigung nicht einfach gewesen war, zeigen Aussagen von Microsoft-Projektleiter Ben Slivka über das JDK beziehungsweise die Java Foundation Classes, man müsse sie »bei jeder sich bietenden Gelegenheit anpissen« (»pissing on at every opportunity«).[2]
Im Januar 2004 beendete die Arbeit an Microsoft J++, denn die Energie floss in das .NET-Framework und der .NET-Sprachen. Am Anfang gab es mit J# eine Java-Version, die Java-Programme auf der Microsoft .NET-Laufzeitumgebungen CLR ausführt, doch Anfang 2007 wurde auch J# eingestellt. Das freie IKVM.NET (http://www.ikvm.net/) ist eine JVM für .NET und kommt mit einem Übersetzter von Java-Bytecode nach .NET-Bytecode, was es möglich macht, Java-Programme unter .NET zu nutzen. Das ist praktisch, denn für Java gibt es eine riesige Anzahl von Programmen, die somit auch für .NET-Entwickler zugänglich sind.
Microsoft hat sich aus der Java-Entwicklung nahezu vollständig zurückgezogen. Es gibt zum Beispiel noch den Microsoft JDBC Driver for SQL Server und Microsoft unterstützt eine API für Office-Dokumente. Das Verhältnis ist heute auch deutlich entspannter und vielleicht gratuliert Microsoft wie es auch Linux zum 20 Geburtstag gratuliert hat[3] irgendwann einmal Oracle.
[1] http://www.microsoft.com/presspass/legal/charles.mspx
[2] Würden wir nicht gerade im westlichen Kulturkreis leben, wäre diese Geste auch nicht zwangsläufig unappetitlich. Im alten Mesopotamien steht »pissing on« für »anbeten«. Da jedoch die E-Mail nicht aus dem Zweistromland kam, bleibt die wahre Bedeutung wohl unserer Fantasie überlassen.
[3] http://www.youtube.com/watch?v=ZA2kqAIOoZM
Neue Open Source Lib zum Generieren von Word-Dokumenten
Performante Ereignisbearbeitung durch LMAX Architektur
Wer performante Systeme entwickelt, sucht immer nach neuen Ideen. Martin Fowler beschreibt in seinem Blog http://martinfowler.com/articles/lmax.html die Architekturform LMAX einer Trading-Anwendung. Auch die PDF http://disruptor.googlecode.com/files/Disruptor-1.0.pdf beschreibt die Architektur und geht Fragen auf den Grund wie: Was kosten Locks, wo ist das Problem bei Queues, …? Mehr Infos gibt auch der Blog http://blogs.lmax.com/ und der Herz der Implementierung ist quelloffen: http://code.google.com/p/disruptor/.
Einrückungen und Klammern – so nicht
So nicht:
private final boolean cvc(int i) { if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false; { int ch = b[i]; if (ch == 'w' || ch == 'x' || ch == 'y') return false; } return true; }
Erstaunlicherweise stammt der Code nicht von irgendeinem Programmieranfänger, sondern von Martin Porter, dem “Erfinder” des Porter Stemming Algorithmus.
Sehr hübsche JavaScript Select-Boxen auch mit muli-Auswahl
biete das Projekt Chosen: http://harvesthq.github.com/chosen/.
Chosen is a JavaScript plugin that makes long, unwieldy select boxes much more user-friendly. It is currently available in both jQuery and Prototype flavors.
Exzellent!
JDK 7 ist da … und schon gleich die ersten Probleme
Am 7.7 wurde Java 7 ja schon weltweit gefeiert wir eine neue CD von Justin Biber. Heute ist der 28.07. und damit das offizielle Release-Datum. Eigentlich läuft das ganz rund, ABER mit HotSpot gibt es einen richtig harten Fehler: http://www.lucidimagination.com/search/document/1a0d3986e48a9348/warning_index_corruption_and_crashes_in_apache_lucene_core_apache_solr_with_java_7. Tja, dumm gelaufen.
Thema der Woche: CAL10N
- Wiederhole http://openbook.galileocomputing.de/javainsel/javainsel_15_004.htm#mj96ec8d1bc0e71c464c41b370dd1db21b.
- Ließ http://cal10n.qos.ch/manual.html.
- Verstehe http://download.oracle.com/javase/1.4.2/docs/guide/nio/example/Grep.java.
- Schreibe Grep so um, dass statt System.err CAL10N genutzt wird. Realisiere dabei Englisch und Deutsch. Teste die Sprachen auf der Kommandozeile mit dem Schalter –Duser.language.
Weld Update 1.1.2
Von der CDI-Referenzimplementierung http://seamframework.org/Weld gibt es ein Update: https://issues.jboss.org/secure/ReleaseNote.jspa?projectId=12310891&version=12316278. Download wie üblich unter http://seamframework.org/Weld/WeldDistributionDownloads.
Gastbeitrag: Bubbles in Swing
In vielen modernen Web-Anwendungen findet sich immer wieder eine Komponente, die bei einem Klick aktiviert wird und an Ort und Stelle auftaucht. Sie lässt sich im weitesten Sinne mit dem Wort "Popup", "Balloontip" oder "Bubble" beschreiben, wie zum Beispiel im Google Kalender:
Solche Komponenten stellen nicht nur Informationen dar, sondern bieten auch Funktionen zur Weiterverarbeitung an und können als Ersatz für viele Dialoge fungieren. Spätestens seit dem Code Bubbles Projekt ist der Nutzen auch für den Endanwender solcher Komponenten ersichtlich.
Update auf Android 3.2 Plattform
Java 7 Unterstützung für Eclipse 3.7 (beta)
Von http://wiki.eclipse.org/JDT/Eclipse_Java_7_Support_%28BETA%29: Über Help > Install New Software wähle die Seite http://build.eclipse.org/eclipse/java7patch/. Dann installieren, neu starten und fertig.
Ein Blog-Beitrag zu mutli-catch: http://thecoderlounge.blogspot.com/2011/07/java-7-support-in-eclipse-jdt-beta-part.html.