Startseite < Informatik < Algorithmen Datenstrukturen / Software-Engineering / Programmiersprachen < Compiler Interpreter / Java < [ DRUCK , 2004 , 2005 , 2006 , 2007 , 2008 , 2009 ] Java-Snippets > C/C++ POV-Ray LaTeX > / Künstliche Intelligenz > Schach Privates / Inhalt >
Java-Snippets
Java-Schnipsel, die häufig benötigt werden.
Einführung Einführung zu Java-Snippets
Auf vorliegender Seite möchte ich einige häufig benötigte Java-Schnipsel (Java-Snippets) vorstellen, die mir — hätte ich diese schnell zur Hand gehabt — etwas Entwicklungszeit erspart hätten. 1 Die vorliegenden Snippets sind für etwas versiertere Java-Entwickler, die mit unkommentiertem Java-Code keine größeren Schwierigkeiten haben, gedacht.
Plattform
Zunächst möchte ich einige kleinere Snippets vorstellen, die die darunterliegende Plattform (Betriebssystem) betreffen. Auch wenn Java eine plattformunabhängige Programmiersprache ist, muss man in seltenen Fällen die darunterliegende Plattform berücksichtigen (wie z. B. bei der Verwendung des Zeilenumbruches), damit die zu entwickelnde Java-Applikation auf jeder Plattform gleichermaßen funktioniert.
Snippet: Zeilenumbruch ermitteln
Wie allseits bekannt, hängt der ASCII-Code eines Zeilenumbruchs vom zugrundeliegenden Betriebssystem ab. Hierzu kenne ich schon drei Varianten:
  1. Unix: „0x0A”
  2. Windows: „0x0D0A”
  3. Mac OS (sogar versionsabhängig): „0x0D” oder „0x0A”
Wie geht also das plattformunabhängige Java damit um? Der für die darunterliegende Plattform korrekte Zeilenumbruch steht in den System-Properties mit der Bezeichnung „line.separator”. Das folgende Snippet stellt eine Methode dar, die immer einen korrekten Zeilenumbruch liefert.
public static String nl() {
  return System.getProperty("line.separator");
}
/* Usage:
System.out.print("Die Sterntaler" + nl() + "Es war einmal ...");
*/
Snippet: Einblick in die System-Properties.
Nicht nur der plattformabhängige Zeilenumbruch steht in den System-Properties, sondern auch andere nützliche Werte wie zum Beispiel der „file.separator”. Um sich einen Überblick zu verschaffen, testen Sie doch bitte folgendes Snippet.
java.util.Properties ps = System.getProperties();
for (Object key : ps.keySet()) {
  System.out.println(String.format("%s='%s'", key, ps.get(key)));
}
/* Output-Snippet:
...
user.country='DE'
user.language='de'
...
os.name='Windows XP'
os.version='5.1'
os.arch='x86'
...
java.version='1.6.0_15'
...
file.separator='\'
...
*/
Strings
Snippet: String.split()
Die Stringmethode split(String regex) eignet sich besonders gut zur Deserialisierung von einfachen Listen. Wenn zum Beispiel ein kommaseparierter String (csv) vorliegt, hilft die Stringmethode split().

Mit diesem KnowHow und ein bisschen Entwurfsmusterwissen ist es Ihnen möglich, einen Iterator für CSV-Strings zu entwickeln. Die Entwicklung eines CSV-Datei-Scanners mit Hilfe von String.split() wäre ebenfalls eine nette Aufgabe.

Im Folgenden werden zwei Methoden vorgestellt:
  1. Strings.getFirst()

    spaltet das erste Element eines separierten Strings ab und
  2. Strings.getLast()

    das letzte.
Auf null muss dabei nicht geprüft werden.
public class Strings {

  public static String getFirst(String separatedList, String separator) {
    if ((separatedList != null) && (separator != null)) {
      for (String first : separatedList.split(separator)) {
        return first;
      }
    }
    return "";
  }

  // Usage:
  // System.out.println(Strings.getFirst("bob@openimscore.org", "@"));

  public static String getLast(String separatedList, String separator) {
    String result = "";
    if ((separatedList != null) && (separator != null)) {
      for (String item : separatedList.split(separator)) {
        result = item;
      }
    }
    return result;
  }

  // Usage:
  // System.out.println(Strings.getLast("www.stefan-baur.de", "."));

  // ...
Files
Snippet: fileCopy
Das Snippet fileCopy implementiert das Kopieren einer beliebigen Datei. Die Eingabedatei from wird KB-weise in die Ausgabedatei to kopiert. Um die Ausnahme FileNotFoundException zu vermeiden, muss die Eingabedatei sowie das Verzeichnis der Ausgabedatei existieren. Die Rückgabe der Funktion stellt die Gesamtanzahl der kopierten Zeichen dar.

Mein erster Versuch die Kopiermethode mit FileReader und FileWriter zu implementieren, schlug aufgrund von Encoding-Problemen fehl; Nicht jede Ausgabedatei war mit der Eingabedatei identisch. Encoding-Probleme gab es generell mit Binärdateien und so mancher RTF-Datei. Daher entschied ich mich für die FileStreams FileInputStream und FileOutputStream.
public static int fileCopy(String from, String to) throws IOException {

  int result = 0;
  byte[] buffer = new byte[1024];

  FileInputStream in = new FileInputStream(from);
  FileOutputStream out = new FileOutputStream(to);

  for (int count = 0; (count = in.read(buffer)) != -1; result += count) {
    out.write(buffer, 0, count);
  }

  in.close();
  out.close();

  return result;
}

// Usage:
// int fileSize = fileCopy("input.txt", "output.txt");
Snippet: dirCopy
Das Snippet dirCopy ist dazu da, das gegebene Verzeichnis from mit samt seinen Inhalten und Unterverzeichnissen rekursiv in das Ausgabeverzeichnis to zu kopieren.
public static void dirCopy(File from, File to) throws IOException {

  if (from.isDirectory()) {

    /* Verzeichnis kopieren */

    if (!to.exists()) {
      to.mkdirs();
    }
    for (String child : from.list()) {
      dirCopy(new File(from, child), new File(to, child));
    }

  } else {

    /* Datei kopieren */

    byte[] buffer = new byte[1024];

    FileInputStream in = new FileInputStream(from);
    FileOutputStream out = new FileOutputStream(to);

    for (int count = 0; (count = in.read(buffer)) != -1;) {
      out.write(buffer, 0, count);
    }

    in.close();
    out.close();
  }
}

// Usage:
// dirCopy(new File("C://Meins"), new File("C://Deins"));
Swing
Java-Swing ist eine Komponentenbibliothek für die GUI (grafische Benutzerschnittstelle), die auf AWT aufbaut. Das Schöne bei Java-Swing ist, dass das Aussehen der grafischen Benutzeroberfläche (Look-and-Feel) ausgetauscht werden kann.
Snippet: Erzeugen eines LookAndFeel-Menüs
Dieses Snippet kann eigentlich für jede Java-Swing-Anwendung verwendet werden. Es ermöglicht dem Anwender zur Laufzeit das Look-and-Feel des Programms über das Menü zu wecheln. Es werden die auf der Java-Plattform installierten LookAndFeel-Masken ermittelt und in einer Radiogruppe im Menü angezeigt.
public static JMenu createLookAndFeelMenu(Component component) {
  JMenu result = new JMenu("Look and Feel");
  ButtonGroup group = new ButtonGroup();
  for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
    JRadioButtonMenuItem item = new JRadioButtonMenuItem(info.getName());
    group.add(item);
    result.add(item);
    item.putClientProperty("INFO", info);
    item.putClientProperty("COMPONENT", component);
    item.setSelected(UIManager.getLookAndFeel().getName().equals(info.getName()));
    item.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        JRadioButtonMenuItem item =
          (JRadioButtonMenuItem)ie.getSource();
        if (item.isSelected()) {
          LookAndFeelInfo info = (LookAndFeelInfo)item.getClientProperty("INFO");
          Component component = (Component)item.getClientProperty("COMPONENT");
          try { UIManager.setLookAndFeel(info.getClassName()); }
          catch (Exception e) { e.printStackTrace(); }
          SwingUtilities.updateComponentTreeUI(component);
        }
      }
    });
  }
  return result;
}
/* Usage:
JFrame frame = new JFrame();
JMenuBar menuBar = new JMenuBar();
menuBar.add(createLookAndFeelMenu(frame));
frame.setJMenuBar(menuBar);
frame.setVisible(true);
*/
Snippet: LookAndFeel anhand einer Prioliste setzen
Wenn Sie zum Beispiel das ansprechende, vollständig vektorbasierte LookAndFeel Nimbus, welches erst mit Java 1.6 Update 12 eingeführt wurde, bevorzugen, besteht die Gefahr, dass Java dieses LookAndFeel (noch) nicht kennt. Mit dem vorliegenden Snippet können Sie eine LookAndFeel-Liste angeben, die solange von vorne nach hinten durchgegangen wird, bis ein LookAndFeel gesetzt werden konnte.
private void setLookAndFeel(String[] prio) {
  for (String name : prio) {
    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
      if (info.getName().equals(name)) {
        try {
          UIManager.setLookAndFeel(info.getClassName());
          SwingUtilities.updateComponentTreeUI(this);
          return;
        } catch (Exception e) { e.printStackTrace(); }
      }
    }
  }
}
/* Usage:
this.setLookAndFeel(new String[] { "Nimbus", "GTK++", "Metal", "Windows" });
*/
Entwurfsmuster
Snippets für Entwurfsmuster dürfen selbstverständlich auch nicht fehlen.
Snippet: Singleton
Ein oft verwendetes Entwurfsmuster ist das Singleton, welches einen privaten Konstruktor hat. Anstelle des Konstruktors verwendet man stets die statische Methode „getInstance()”. Ähnlich wie beim Konstruktor „new” gibt auch die Methode „getInstance()” immer eine Instanz der Klasse (hier: MySingleton) zurück, nur mit dem wesentlichen Unterschied, dass immer die selbe Instanz zurückgegeben wird.
public class MySingleton {

  private static MySingleton self = null;

  private MySingleton() {}

  public static MySingleton getInstance() {
    if (self == null) {
      self = new MySingleton();
    }
    return self;
  }

  public void yourMethod() {
    System.out.println("dummy");
  }
}

/* Usage:
MySingleton.getInstance().yourMethod();
*/
Snippet: Supergenerisches Besuchermuster
Für die Entwicklung des vorliegenden supergenerischen Besuchermusters hatte ich besonders viel Zeit investiert. Dass sich dieser Aufwand gelohnt hat, sehen Sie heute am Beispiel Tinyray-Visitors.
// Visitor.java
public interface Visitor<R, A> {
  R visit(NodeA nodeA, A argument);
  R visit(NodeB nodeB, A argument);
  // NodeC, ...
}

// Visitable.java
public interface Visitable {
  <R, A> R accept(Visitor<R, A> visitor, A argument);
}

// NodeA.java (dummy)
public class NodeA implements Visitable {
  public <R, A> R accept(Visitor<R, A> visitor, A argument) {
    return visitor.visit(this, argument);
  }
  // your code here
}

// NodeB.java (dummy)
public class NodeB implements Visitable {
  public <R, A> R accept(Visitor<R, A> visitor, A argument) {
    return visitor.visit(this, argument);
  }
}

// NodeC.java, ...

// ClassNameVisitor.java (dummy)
public class ClassNameVisitor implements Visitor<String, Boolean> {

  public String visit(NodeA nodeA, Boolean simple) {
    if (simple) return nodeA.getClass().getSimpleName();
    else return nodeA.getClass().getName();
  }

  public String visit(NodeB nodeB, Boolean simple) {
    if (simple) return nodeB.getClass().getSimpleName();
    else return nodeB.getClass().getName();
  }

  // NodeC, ...
}
Threads

Snippet: JFrame mit Thread
Immer wenn es um Threads geht, habe ich immer die Befürchtung etwas falsch zu machen, so dass ich mir auch hierfür ein kleines, bewährtes Skeleton zurechtgelegt habe.
import java.awt.event.*;
import javax.swing.*;

public class MyThreadFrame extends JFrame implements Runnable {

  private static final long serialVersionUID = 1L;

  public MyThreadFrame() {
    this.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) { System.exit(0); }
      public void windowDeiconified(WindowEvent e) { start(); }
      public void windowIconified(WindowEvent e) { stop(); } });
  }

  private Thread myThread;

  public void start() {
    this.myThread = new Thread(this);
    this.myThread.setPriority(Thread.MIN_PRIORITY);
    this.myThread.start();
  }

  public synchronized void stop() {
    this.myThread = null;
  }

  public void run() {
    Thread currentThread = Thread.currentThread();
    while (this.myThread == currentThread) {

      this.dummyAction(); // Replace it with your action!

      try { Thread.sleep(10); }
      catch (InterruptedException e) { break; }
    }
    this.myThread = null;
  }

  private int dummyCounter = 0;
  private void dummyAction() {
    this.setTitle(String.format("%d", this.dummyCounter++));
  }

  public static void main(String arguments[]) {
    MyThreadFrame myThreadFrame = new MyThreadFrame();
    myThreadFrame.getContentPane().add(new JLabel(" Minimize this Window!"));
    myThreadFrame.setSize(150, 60);
    myThreadFrame.setVisible(true);
    myThreadFrame.start();
  }
}