Aufgaben zu Java 5

Spracheigenschaften

Erweitertes for (for-each-Schleife)

Das erweiterte for für Felder (25 Minuten)

Gib alle Namen von Dateien und die Unterverzeichnisse eines Verzeichnisses dir aus. Nutze dazu das java.io.File-Objekt und die Methode list() oder listFiles().

String dir = "c:/";
for ( ... )
  System.out.println( file );

Gib mit Hilfe einer passenden Funktion alle Wörter einer Zeichenfolge aus. Die Zeichenfolge "Hallo Welt" soll also "Hallo" und dann "Welt" ausgeben.

String dir = "Hallo Welt";
for ( ... )
  System.out.println( word );

Lösung

Eine eigene Implementierung mit Iterable (40 Minuten)

Finde in der API-Dokumentation Klassen, die java.lang.Iterable implementieren. Schreibe eine statische Funktion readLines(String filename), die eine Datei öffnet und Zeilenweise ausliest. So soll folgendes Programmstück alle Zeilen der Datei auf dem Bildschirm ausgeben.

for ( Object line : FileUtils.readLines("c:/test.txt") )
  System.out.println( s );

Lösung FileUtils, FileUtilsDemo

Autoboxing

valueOf() beim Boxing

Schaue in die Implementierung von Integer.valueOf() und begründe, warum diese Fabrik-Funktion beim Boxing aufgerufen wird, und nicht der Konstruktor.

Behandlung der null beim Unboxing (5 Minuten)

Lässt sich eine Null derart umwandeln: int i = null?

Ist Folgendes zu schreiben sinnvoll?

Map<String,Integer> map = new HashMap<String,Integer>();
map.put( "Eins", 1 );
int eins = map.get( "eins" );

Überraschung beim Unboxing (5 Minuten)

Gesucht ist das Ergebnis der Bildschirmausgaben. Überlege erst, übersetze dann das Programm und beobachte das Ergebnis.

Integer i11 = 1;
Integer i12 = 1;
System.out.println( i11 == i12 );
System.out.println( i11 <= i12 );
System.out.println( i11 >= i12 );

Integer i21 = 1000;
Integer i22 = 1000;
System.out.println( i21 == i22 );
System.out.println( i21 <= i22 );
System.out.println( i21 >= i22 );

Überlagen von Methoden

Kopiere die drei folgenden Methoden und erkläre die Ausgabe:

public static void someOverloadedMethod( int argInt ) {
  out.printf( "In someMethod(int) with type: %s %d%n", int.class.getName(), argInt );
}
public static void someOverloadedMethod( Object argObject ) {
  out.printf( "In someMethod(Object) with type: %s value:%s%n", argObject.getClass().getName(), argObject );
}
public static void main( String[] args )
{
  Integer intWrapper = 1234;
  int intPrim = 4567;
  Object anObjectWithBoxedInteger = 7890;
  someOverloadedMethod( intWrapper );
  someOverloadedMethod( 10 );
  someOverloadedMethod( anObjectWithBoxedInteger );
}


Varargs

Vargs nutzen für Objektsuche in der Datenstruktur (10 Minuten)

Schreibe eine statische Funktion void contains(), die zum einen eine java.util.List bekommt und zum anderen eine variable Liste von Objekten. Die Methode soll boolean liefern, wenn irgendein genanntes Element in der Liste ist. Ein Aufrufbeispiel wäre

List list = Arrays.asList( "Hi", "Wie", "Geht's" );
System.out.println( "contains: " + contains(list, "Hallo", "Hi", "Welcome") );

Lösung

Enums

Die erste Aufzählung

Definiere eine Aufzählung Currency für einige Währungen nach ISO 4217, etwa EUR, USD.

Lösung

Eingaben und Fallunterscheidung

Der Benutzer soll in JOptionPane.showInputDialog() eine Währung nach ISO 4217 eingeben. Für die Eingabe soll das passende enum-Objekt gesucht werden. Eine Fallunterscheidung soll für einige enums eine Meldung auf dem Bildschirm ausgeben.

Lösung

Design einer Umrechungssoftware

Wie kann man mit Hilfe der Klasse EnumMap eine Umrechung programmieren, so dass man eine beliebige Währung in eine andere beliebige Währung umrechnen kann?

 

Generics

String-Liste aufbauen und ablaufen

Erzeuge eine ArrayList, die nur String-Objekte aufnehmen kann. Fülle sie mit ein paar Strings.

Laufe sie mit dem erweiterten for ab.

Typisierungen der Box

Implementiere die Klasse Box<T>.

Methoden-Typisierung statt Klassentypisierung

Warum findet man bei der Klasse ArrayList in der Methode T[] toArray(T[] a) nicht den Typ E, sondern T?

Häufigkeiten zählen (15 Minuten)

Für Wörter aus einer Liste sollen deren Häufigkeiten festgehalten werden. Dazu definieren wir eine Klasse WordCounter mit einer Funktion update(String) und einer Funktion clear(). Eine Funktion getWordCount(String) soll dann zurückgeben, wie oft das Wort bisher vorkam.

public class WordCounter
{
 public void update( String s ) { }
 public void clear() { }
 int getWordCount( String s ) { return 0; }
}

Zum Testen schreibe:

WordCounter wc = new WordCounter();
wc.update( "Hallo" );
wc.update( "Welt" );
wc.update( "Hallo" );
System.out.println( wc.getWordCount("Hallo") );  // 2
System.out.println( wc.getWordCount("Welt") );   // 1
System.out.println( wc.getWordCount("NIX") );    // 0

Lösung

Fragen zu Typeinschränkungen (20 Minuten)

Um java.awt.Point-Objekte in ein HashSet einsortieren zu können, müssen wir einen externen Comparator definieren, da Punkte-Objekte nicht Comparable sind. Schreibe einen mit Point generisch deklarierten Comparator, der den Abstand zum Nullpunkt (euklidisch oder in der Manhatten-Metrik) als Kriterium verwendet.

Set<Point> set = new TreeSet<Point>( comparator );
set.add( new Point(2,3) );
set.add( new Point(9,9) );
set.add( new Point(3,2) );
set.add( new Point(1,1) );
System.out.println( set );

Die Sortierreihenfolge bei der Ausgabe soll etwa sein: (1,1), (2,3); (9,9).

Was kann man mit <?> machen?

Wird es bei folgenden Zeilen einen Compiler-Fehler geben? Wie erklärt sich das Verhalten?

Collection<?> list = new ArrayList<String>();
list.add( "Hallo Welt" );

 

Annotationen

Annotationen als Modifizierer

Wenn eine Annotation ein Modifizierer wie public, static oder final ist, welche Konsequenz hat das?

Markierungsannotationen

Mit EJB 3 ist es möglich, ohne XML-Konfigurationsdateien (aka Deployment-Deskriptor) Enterprise JavaBeans zu schreiben. Ein Beispiel aus dem EJB 3 Tutorial von JBoss:

// import javax.ejb.Stateless;
// import javax.ejb.Remote;

@Remote
@Stateless
public class CalculatorBean // implements Calculator
{
  public int add( int x, int y )
  {
    return x + y;
  }

  public int subtract( int x, int y )
  {
    return x - y;
  }
}

Definiere die dafür nötigen Annotations-Typen.

Elemente für Annotationen

Der Annotations-Typ @Stateless soll um Elemente erweitert werden.

  1. Definiere ein Element name vom Typ String. Es soll standardmäßig auf "" stehen.
  2. Definiere eine neue Aufzählung TransactionManagementType (nicht im Inneren von @Stateless), mit den Elementen CONTAINER und BEAN. @Stateless soll ein Element transactionManagement bekommen, welches standardmäßig auf CONTAINER steht.

Erzeuge eine neue Annotation @Stateful. Kopiere die Elemente aus @Stateless, denn es sind die selben!

@Stateless/@Stateful annotieren

  1. Welcher @Target ist bei @Stateless/@Stateful sinnvoll?
  2. Erzeuge eine neue Annotation @Remove, welches nur auf Methoden angewendet werden darf. Es soll ein Element boolean retainIfException() default false; definieren.
  3. Siehe in der EJB 3 Spezifikation im Kapitel "10.1.1/10.1.2 Stateless/Stateful Session Beans" nach, ob und wie @Retention gesetzt ist.

Zugriff auf die Annotationen

Teste, ob der Typ CalculatorBean eine Annotation trägt. Erfrage, welche Annotationen mit den Klassen verbunden sind.

Annotationen für Testfälle (15 Minuten)

Was macht die folgende Klasse? Bringe das Beispiel mit einem neuen Annotations-Typ @Test zum Laufen.

import java.lang.reflect.Method;

public class TestRunner
{
 static void executeTests( String className )
 {
  try
  {
   executeTests( Class.forName(className) );
  }
  catch ( ClassNotFoundException e )
  {
   e.printStackTrace();
  }
 }

 static void executeTests( Class clazz )
 {
  try
  {
   Object testObject = clazz.newInstance();
   Method[] methods = testObject.getClass().getDeclaredMethods();

   for ( Method amethod : methods )
   {
    Test testAnnotation = amethod.getAnnotation( Test.class );
    if ( testAnnotation != null )
    {
     System.out.print( testAnnotation.value() + " : " );
     String result = invoke( amethod, testObject );
     System.out.println( result );
    }
   }
  }
  catch ( Exception e )
  {
   e.printStackTrace();
  }
 }

 static String invoke( Method m, Object o )
 {
  try
  {
   m.invoke( o, (Object[]) null );
   return "passed";
  }
  catch ( Exception x )
  {
   return "failed";
  }
 }

 public static void main( String[] args )
 {
  executeTests( "ClassToTest" );
//  executeTests( ClassToTest.class );
 }
}

Bibliotheken

Exceptions auffangen (25 Minuten)

Implementiere einen Thread, der durch die Division mit Null eine Exception wirft. Fange den Fehlerfall dieses speziellen Threads durch einen UncaughtExceptionHandler ab.

Lösung

Die Klasse Formatter (10 Minuten)

Sei

double d = 1234567.1234;
Calendar c = Calendar.getInstance();

Wie erhält man die Ausgaben

1234567,12
1.234.567,12
    1.234.567,12  (rechtsbündig auf der Breite von 20 Stellen)  

und den Tag/Monat/Jahr (etwa 11/12/2006) des Kalenders?

Lösung

Die längste Zeile einer Datei

Laufe mit einem java.util.Scanner durch eine Datei und gib Länge der längsten Zeile aus.

Lösung

In einem Rutsch mit dem Scanner (15 Minuten)

Beziehe den Inhalt einer Webseite mit der Scanner-Klasse in nur einer Zeile.

String content = ...
System.out.println( content );

Die folgenden Klassen sind nötig: java.net.URL, java.io.InputStream, java.util.Scanner. Der Trick ist, das richtige Delimiter-Zeichen beim Scanner mit useDelimiter() zu verwenden!

Vergleichen und Ausgabe von Feldern über die Klasse java.util.Arrays

Teste jeweils die statischen Funktionen toString() und deepToString() der Klasse Arrays an folgenden Feldern:

Object[] o = { "Eins", "Zwei", "Polizei", new int[]{1, 2, 3} };
Object[] p = { "Eins", "Zwei", "Polizei", new int[]{1, 2, 3} };

Vergleiche auch die statischen Funktionen equals() und deepEquals().

Anzahl Elemente suchen

Gegeben ist eine Liste mit Strings. Wie beantwortet man die Frage, wie oft ein String in diesem Array vorkommt?

Automatisches Sortieren von Elementen

Bilde einen PriorityQueue und füge die Elemente 1, 9, 3, 10 ein. Hole drei Elemente entfernend aus der Queue. Füge 1, 12 als neue Elemente ein. Lese schlussendlich in einer Schleife alle Elemente löschend aus. Welche Reihenfolge geben der Iterator und toString()?

Lösung

Hashtable, ConcurrentHashMap, sichere Map

Lege eine Hashtable, eine ConcurrentHashMap und eine Map mit einer Collections.synchronizedMap() an. Führe mit jeweils 1, 2, 4, 8, 16, 32 Threads die nachfolgend genannten Operationen 1 Millionen mal aus:

  1. Im Kern wahlfreier Zugriff auf einige Elemente, wobei Treffer und nicht-Treffer dabei sind.
  2. put() und remove() sollten auch vereinzelt vorkommen.

Die Klasse Formatter

Wirf einen Blick auf die Dokumentation der Klasse Formatter. Erzeuge eine Datei und schreibe dort das aktuelle Datum hinein. Für die Aufgabe müssen zwei bis drei Anweisungen reichen.

Teste das Schreiben auch mit unserer neuen Klasse, die ein StringBuffer als Appendable nutzt.

Properties in XML speichern

Erfrage über das System-Objekt die Properties-Eigenschaften und gebe sie als XML-Objekt auf dem Bildschirm aus.

WebRowSet

Schreibe ein Beispiel mit dem WebRowSet (unter Java 5 muss man die Implementierung gesondert laden).

  1. Melde hsqldb.jar im Klassenpfad an.
  2. Binde mit Class.forName() den Datenbanktreiber ein.
  3. Fülle ein WebRowSet mit allen Kunden der Datenbank.
  4. Schreibe mit writeXml() die Daten auf System.out.

Thread-Pool (20 Minuten)

Erzeuge mit ExecutorService s = Executors.newCachedThreadPool(); einen java.util.concurrent.ExecutorService und führe mit s.execute() Programmcode vom folgenden Kern in run() aus java.lang.Runnable aus:

class MyRunnable implements Runnable
{
  public void run()
  {
    System.out.println( Thread.currentThread() );
//  try {
//   Thread.sleep( 1000 );
//  } catch ( InterruptedException e ) {
//   e.printStackTrace();
//  }
  }
}

Das Programm sieht dann so aus:

ExecutorService s = Executors.newCachedThreadPool();
Runnable run = new MyRunnable();
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
s.execute( run );
...

Welchen Unterschied macht es, ob man die Zeilen auskommentiert oder wieder in den Programmfluss integriert?

ArrayBlockingQueue und Threads

Erzeuge eine ArrayBlockingQueue<String> der Größe 2 und zwei Runnable's, die einen Verweis auf die Queue bekommen. Der erste Runnable soll Strings produzieren, der andere konsumieren, doch sich dabei 100 ms Zeit lassen. Achte beim Herausnehmen und Einlegen auf die richtigen Funktionen.

Management

Starte notepad und dann die jconsole.