Links und Literatur

Java Aufruf

Java mit mehr Speicher starten

java -Xmx512m

Bestimmte Java Version erzwingen

java -version:1.4

Java Programm compilieren und ausführen

Achtung, das Trennzeichen unter Windows ist nicht ":" sondern ";".

So erzeugt man aus einer .java Datei eine .class Datei

javac -classpath "foo/bar.jar:foo/tests.jar:../foo.jar" MyClass.java

Dabei muss man alle jar Dateien angeben, die direkt von der Klasse genutzt werden (also nicht die, die nur von Klassen genutzt werden, die wir aufrufen).

So erzeugt man jar Dateien

jar cf MyJar.jar MyClass.java

Siehe auch die JAR Dateien erzeugen Anleitung.

So führt man das Java Programm dann aus (jetzt muss man wirklich all jars auflisten die zur Ausführung gebraucht werden)

# java -classpath "foo/bar.jar:foo/tests.jar:../foo.jar:../misc.jar" MyClass

Java debuggen

So kann man auf einem entfernten Rechner Java so starten, dass es im lokalen Debugger untersucht werden kann

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n ...

Dabei sorgt

suspend=y dafür, dass das Programm erst losläuft, wenn der Debugger verbunden ist.

Um den Debugger einzurichten, in Eclipse

open debug digalog
remote java application
new
Rechnername und Port des Java Programms

Data Containers

JavaDataContainers

Java Classes

JavaClasses

Autoboxing

int i     = 4711;
Integer j = i; // j = Integer.valueOf(i)
int k     = j; // k = j.intValue()

Gleichheit

int x,y;
Foo a, b;

x==y // (1)

a==b // (2)

a.equals(b); (3)

(1) Bei Basistypen ein normaler Test auf Gleichheit (2) Ansonsten Test ob beides eine Referenz auf das gleiche Objekt ist (3) Inhaltliche Gleichheit mit equals() testen

Wenn man equals nicht selbst implementiert sieht es so aus: und equals selbst implementieren, default ist das:

public boolean equals( Object obj )
{
  return ( this == obj );
}

Eine mögliche Implementierung:

public boolean equals( Object obj )
{
  if ( obj instanceof Foo ) {
    Foo tmp = (Foo) obj;
    return (bar == tmp.bar)
  }
  return super.equals( obj );
}

Als Parameter aber Object erwarten und nicht die Klasse für die die Methode gedacht ist. Also nicht:

//public boolean equals(Foo fooObj) {...};

Achtung, wenn man equals ändert, darauf achten, dass aus a.equals(b) auch a.hashcode()==b.hashcode() folgen muss (umgekehrt aber nicht). Eclipse kann für equals() und hashcode() sinnvolle Vorschläge machen.

Achtung, die Reihenfolge beim equals() Vergleich ist z.B. dann relevant, wenn einer der beiden Objekte null werden kann. Ist z.B. a potentiell null, b hingegen nicht, kann man das equals von a natürlich nicht aufrufen

// a.equals(b);
b.equals(a);

Können beide null sein, diesen Fall vorher extra abfangen (sonst gibt es eine Exception wenn versucht wird equals auf null aufzurufen).

Conditional Expressions

Kurzschreibweise für bedingte Zuweisung

//if(ungerade) max=l; else max=l-1;
int max=(ungerade) ? l : l-1;

Vorsicht bei conditional operator x ? y : z wenn y und z verschiedene Typen haben, vor allem wenn y oder z keinen konstanten Wert haben oder nicht vom Typ byte short char sind, dann tritt eine Konvertierung in Kraft mit möglicherweise unerwartetem Ergebnis.

Kurzschlußoperatoren

boolean b1 = true || foo(); // (1)
boolean b2 = true | foo(); // (2)
boolean b3 = false & foo(); // (3)

(1) foo() wird nicht aufgerufen (2) foo() wird aufgerufen (3) foo() wird aufgerufen

Compound Assignment Operator

x=x+y;  // A
x+=y; //B
x=+y; //C

Dabei ist B ist bekannt als Kurzschreibweise für A, allerdings unterscheidet sich B im Verhalten leicht von A, da in Java bei B versucht wird, durch einen Cast den Typ von y auf den Typ von x anzupassen.

Das hier ist z.B. valider Java Code

byte x=0;
int  y=128;
x+=y;

Das hier hingegen nicht

byte x=0;
int  y=128;
x=x+y;

Allerdings liefert der versteckte Cast denoch ein vermutlich unerwartetes Ergebnis, weil 128 gar nicht in eine byte Variable passt.

Umgekehrt unterliegt B aber auch Einschränkungen, denen A nicht unterliegt. So muss in B x ein primitiver (boxed) Datentyp oder String sein.

Object x = "Hello";
String y = "World";

x = x + y;  // OK
x += y;     // Error

C sieht so ähnlich aus wie B weißt aber einfach nur x den Wert von y zu (ohne das Vorzeichen von y irgendwie zu verändern).

Undefinierte Parameter Anzahl

Methoden können eine undefinierte Anzahl an Parametern erwarten, ansprechbar wie ein Array

int max( int... x)
{
 System.out.println(x.lenght);
}

Überdeckte Namen

void foo(int x)
  {
   x = 12;              // (1)
   this.x = 12;         // (2)
   this.x=x;
 }

(1) Zuweisung an lokale Variable x (2) Zuweisung an Objektvariable x

Override

Optional erklären dass man eine Methode des Vaters überschreibt (Fehler falls nicht)

@Override
public void foo( int alter )

Lazy Initialization

Die Initialisierung wird hinausgezögert, bis sie wirklich gebraucht wird.

Anstatt also ein Attribut sofort mit einem Wert zu belegen

private final Integer foo=initFoo();

Verzögert man das, bis der Wert erstmalig ausgelesen wird

private Integer foo;
public synchronized Integer getFoo()
{
 if(foo==null) foo=initFoo();
 return foo;
}

Für statische Attribute gibt es einen eleganten Trick. Man nutzt eine kleine statische Klasse, die nur das Attribut und dessen Initialisierung enthält. Erst wenn dieses Attribut zum ersten Mal benutzt wird, wird auch die Klasse zum ersten Mal benutzt und die Initialisierung läuft an. Ein manuelles synchronized ist nicht notwendig.

private static class FooHolder
{
 static final Integer foo = initFoo();
}

static Integer getFoo()
{
 return FooHolder.foo;
}

Wenn man ein nicht statisches Attribut hat und vermeiden will, und Performance Verluste mit einem synchronized Getter vermeiden will, kann man das double-check idiom verwenden

private volatile Integer foo;

public Integer getFoo()
{
 Integer tmp=foo;
 if(tmp==null)
 {
  synchronized(this)
  {
   tmp=foo;
   if(tmp==null) foo=tmp=initFoo();
  }
 }
 return tmp;
}

Wichtig ist, dass das Attribut volatile ist, damit Änderungen von einem Thread von allen Threads gesehen werden. Sollte ein Thread das Attribut nicht initialisiert vorgefunden haben, testet er das nochmal, nur diesmal synchronized, damit wird verhindert, dass mehr als einmal initialisiert wird. Falls eine mehrfache initialisierung nicht stört, kann man diesen Schritt auch weglassen, das nennt man dann single-check idiom.

Die lokale Variable tmp ist nicht zwingend notwendig, verbessert aber die Performance.

final

Variable nicht änderbar (wohl aber Methoden aufrufbar die sie ändern)

final int x=3;
final Foo y=new Foo();
y.reset();

Erben nicht möglich

final class Bar
{
 // ...
}

Überschreiben nicht möglich

class Foo
{
 final void bar();
}

Generische Datentypen / Generics

class Foo<T>
{
  private T val;

  void setValue( T val )
  {
    this.val = val;
  }

  T getValue()
  {
    return val;
  }
}

Foo<String>  stringFoo = new Foo<String>();
Foo<Integer> intFoo    = new Foo<Integer>();
Foo<Point>   pointFoo  = new Foo<Point>();

class Bar
{
  public static <T extends Number> T myMethod( T a, T b, HashMap<T, String> )
  {
   //...
  }
}

So kann man von einer generischen Klasse erben, ohne deren generischen Typ weiter einzuschränken.

public class Bar<T> extends Foo<T> { ... }

Macht man das falsch erhält man oft diesen Fehler

A supertype may not specify any wildcard

Manchmal will man den Typen dabei aber auch weiter einschränken. Hier ein Beispiel wie es geht. Angenommen man hat eine einfache Klassenhierarchie, z.B. verschiedene Hunde

public class Dog
{
    public void bark()
    {
        System.out.println("Wuff!");
    }
}

public class Poodle extends Dog
{

    public void barkLikeAPoddle()
    {
        System.out.println("Wuff, Wuff!");
    }
}

public class FrenchPoodle extends Poodle
{
    public void barkLikeAFrenchPoddle()
    {
        System.out.println("Wüff, Wüff!");
    }
}

Und jetzt möchte man parallel dazu eine weitere Klassenhierarchie haben. Diese neue Hierarchie soll jetzt mit der ersten verbunden werden. Bestimmte Stufen der neuen Hierarchie arbeiten nur mit bestimmten Klassen der ersten Hierarchie zusammen. Eine Möglichkeit das abzubilden sind Generics. Zum Beispiel soll es jetzt verschiedene Hundehütten geben, die nur bestimmte Hunde akzeptieren.

public class DogHouse<T extends Dog>
{
    protected T dogInTheHouse;

    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
    }
}

Trickreich sind hier die Zwischenklassen, die bereits von einer anderen Klasse mit Einschränkung auf den Typ erben, sich aber auf den Typ noch nicht final festlegen. Besondern schwierig ist es, in einer solchen Zwischenklasse neue Objekte des eingebetteten Typs zu erzeugen, weil die Klasse nie wissen kann, für welchen Typ sie später benutzt wird.

public class DogHouseForAPoodle<T extends Poodle> extends DogHouse<T>
{  
    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
        this.dogInTheHouse.barkLikeAPoddle();
    }

    public void assignementIsEasy(T newDog)
    {
        this.dogInTheHouse=newDog;
    }

    /*
    public void butCreationIsTricky()
    {
        this.dogInTheHouse=new Dog();          // Fails because T might be Poodle
        this.dogInTheHouse=new Poodle();       // Fails because T might be FrenchPoodle
        this.dogInTheHouse=new FrenchPoodle(); // Fails because T might be something which also extends Poodle
    }
    */

}

Das ist wieder leicht:

public class DogHouseForAFrenchPoodle extends DogHouseForAPoodle<FrenchPoodle>
{
    public void wakeTheDog()
    {
        this.dogInTheHouse.bark();
        this.dogInTheHouse.barkLikeAPoddle();
        this.dogInTheHouse.barkLikeAFrenchPoddle();
    }
}

Javadoc

/**
* @see  Bar
* @link Bar
* @version 1.01
* @author John Doe
* @param x A number
* @param y Another number
* @return This method always returns 5
* @exception NumberFormatException
* @throws    NumberFormatException
* @category Setter
* @deprecated Since yesterday
*/

public int foo(int x, float y)
{
  return 5;
}

Exceptions

try
 {
  // ...
  return 5;
 }
 catch ( Exception e )
 {
  System.err.println( "Error");
 }
 finally
 {
  ... // (1)
  // return 7; (2)
 }

(1) auf jeden Fall, auch nach dem return (2) keine Exception kann nach oben durchgereicht werden

Wann wird finally ausgeführt

In diesem Beispiel nutzen alle return Anweisungen eine Methode um den Rückgabewert zu ermitteln. Dadurch kann man dokumentieren, wann die einzelnen return Anweisungen aufgerufen werden

public static String getStringValueAndLogIt(String pValue)
{
 System.out.println("Here is your String value: "+pValue);
 return pValue;
}

@SuppressWarnings("finally")
public static String doSomething(boolean pDoException)
{
 System.out.println("Method entered");
 try
 {
  System.out.println("Try block entered");
  if(pDoException) throw new Exception("Bang!");
  return getStringValueAndLogIt("NormalReturn");
 }
 catch(Exception e)
 {
  System.out.println("Exception occured");
  return getStringValueAndLogIt("ExceptionReturn");
 }
 finally
 {
  System.out.println("Finally block entered");
  // do not use return in a finally block!
  return getStringValueAndLogIt("FinallyReturn");
 }
}

Falls keine Exception auftritt:

Method entered
Try block entered
Here is your String value: NormalReturn
Finally block entered
Here is your String value: FinallyReturn

Falls eine Exception auftritt

Method entered
Try block entered
Exception occured
Here is your String value: ExceptionReturn
Finally block entered
Here is your String value: FinallyReturn

Man sieht also, in beiden Fällen wird erst das return aufgerufen und dann erst den finally Block. Das ist auch sehr sinnvoll, weil natürlich auch das return Statement eine Exception auslösen könnte. Da der finally Block selbst wieder ein return enthält (was man tunlichst vermeiden sollte) setzt dieser sich am Ende durch und die Methode liefert in beiden Fällen

FinallyReturn

zurück.

Eigene Exceptions

public class ClubException extends RuntimeException
{
  public ClubException()
  {
  }

  public ClubException( String s )
  {
    super( s );
  }
}

Stacktrace

kill -3 PID
[[http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstack.html | jstack ]] PID;
Thread.dumpStack();

Assert

Sicherstellen dass die gegebene Bedingung erfüllt ist

assert(i>0);

Überwachung der Assertions aktivieren

java -enableassertions      foo
java -enableassertions:bar foo

Multithreading

JavaMultithreading

Dateien und Verzeichnisse

Java is auch eine Insel: Dateien und Verzeichnisse.

JSON

Create a class to hold the values, e.g. for a person, add annotations to its constructor

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Person {
    private final String name;
    private final Integer age;

    @JsonCreator
    public Person(@JsonProperty("name") final String name, @JsonProperty("age") final Integer age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }
}

Turn an object into a JSON String, and a JSON String into an object

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class JsonPlay {

    public static void object2JsonString() throws JsonProcessingException {
        // http://www.studytrails.com/java/json/jackson-create-json.jsp

        final ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
        mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
        mapper.setSerializationInclusion(Include.NON_EMPTY);

        final Person john = new Person("John Jones", 42);
        final String jsonString = mapper.writeValueAsString(john);
        // { "name" : "John Jones", "age" : 42 }
        System.out.println(jsonString);

    }

    public static void jsonString2Object() throws JsonParseException, IOException {
        final String json = "{ \"name\" : \"John Jones\", \"age\" : 42 }";
        final ObjectMapper mapper = new ObjectMapper();
        final Person john = mapper.readValue(json, Person.class);
        System.out.println(john);
    }

Java XML

JavaXML

CSV Dateien auslesen

OpenCSV

import au.com.bytecode.opencsv.CSVReader;
...

  CSVReader reader = new CSVReader("Foo.csv", ',');
  List<String[]> myEntries = reader.readAll();

Excel Dateien schreiben und lesen

Apache POI

import java.io.File;
import java.io.FileOutputStream;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

...

XSSFWorkbook workbook=new XSSFWorkbook();
XSSFSheet sheet = workbook.createSheet("My Excel Sheet");
XSSFRow  row0  = sheet.createRow(0);
{
 XSSFCell cell0 = row0.createCell(0);
 XSSFCell cell1 = row0.createCell(1);
 cell0.setCellValue(Number);
 cell1.setCellValue(Date);
}

XSSFRow  row1  = sheet.createRow(1);
{
 XSSFCell cell3 = row1.createCell(1);
 cell3.setCellValue(42);

 XSSFCell cell4 = row1.createCell(2);
 cell4.setCellValue(new Date());

 XSSFCellStyle cellStyle = workbook.createCellStyle();
 cellStyle.setDataFormat(workbook.getCreationHelper().createDataFormat().getFormat("yyyy-mm-dd"));                  
 cell4.setCellStyle(cellStyle);
}

sheet.autoSizeColumn(0);
sheet.autoSizeColumn(1);

File output=new File(“excelfile.xlsx);
FileOutputStream out = new FileOutputStream(output);
workbook.write(out);

out.close();

Access file located in the classpath

URL url = this.getClass().getClassLoader().getResource(pFilename);
if(url!=null)
{
    return url.getPath();
}

This would look for the file directly in src/main/resources. However, you should create subfolders there matching the class package (e.g. if the package would be de.tgunkel.java create de/tgunkel/java/) and put the file there. In order to access it there use (without getClassLoader)

URL url = this.getClass().getResource(pFilename);

Add / in front of the the filename would again access files in the root folder.

You should avoid to get the URL first and then try to read it but use getResourceAsStream to directly get a stream, no matter how wired the URL might be (e.g. a file inside a JAR)

Example

private String testFileContent(final String filename) throws IOException {
        try (InputStream in = getClass().getResourceAsStream(filename)) {
                final String myString = IOUtils.toString(in, "UTF-8");
                return myString;
        }
}

Reguläre Ausdrücke

Häufig möchte man aus einem String bestimmte Teile ausschneiden und dann neu zusammensetzen. Ein typisches Beispiel ein Datum liegt in dieser Form vor

13/07/2013

und soll in diese Form übertragen werden

2013-07-13

Mit einer sogenannten Backreference kann man jetzt Tag, Monat und Jahr erst durch einen regulären Ausdruck erfassen und Klammern. Danach dann via $1, $2, $3 wieder ausgeben lassen

string s=s.replaceAll("([0-9]*)/([0-9]*)/([0-9]*)", "$3-$2-$1");

Und schon hat man ein Format welches Date versteht

java.sql.Date d=java.sql.Date.valueOf(s);

Aus einem String eine Regexp erzeugen, die auf diesen String passt (nützlich um Escape Zeichen zu erzeugen) String s=java.util.regex.Pattern.quote("Hallo Welt");

Ein Trick zum Escapen eines ganzen Bereiches geht übrigens so

Reflection

Class c=null;
try
{
  c = Class.forName("foo");
} catch (ClassNotFoundException ex)
{
  // ...
}

Annotations

So macht man seine eigene Annotation

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface XMLGeneratorAnnotation
{
    String elementName() default "";
    int    elemntOrder() default 0;
}

So ermittelt man alle Attribute eines Objektes und seine Werte

for(Field f : myObject.getClass().getDeclaredFields())
{
    f.setAccessible(true);
    MyAnnotation a=f.getAnnotation(MyAnnotation.class);
    try
    {
        f.getName();
        f.get(myObject);
    }
    catch (IllegalArgumentException | IllegalAccessException e)
    {
    }
    finally
    {
    }
}

So ermittelt man alle Methoden eines Objektes und ruft sie auf

for(Method m : myObject.getClass().getDeclaredMethods())
{
    m.setAccessible(true);

    ElementContainer container=new ElementContainer();

    MyAnnotation a=m.getAnnotation(MyAnnotation.class);
    try
    {
        m.getName();
        m.invoke(myObject);
    }
    catch (IllegalAccessException | IllegalArgumentException  | InvocationTargetException e)
    {
    }
    finally
    {
    }
}

Apache Commons

Nützliche Java Komponenten Apache Commons.

Objekte in Strings umwandeln

ToStringBuilder

ToStringBuilder.reflectionToString(this);
new ToStringBuilder(this).append("Name: ", name).append("ID: ", id).toString();

String in Zahl konvertieren

[[http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Integer.html#parseInt(java.lang.String,%20int) | Integer.parseInt ]]("042", 10);

0 Padding

So kann man den String year mit führenden Nullen auf 4 Stellen auffüllen:

String s=String.format("%04d",year);

Syntax:

%[flags][width]conversion

Flags '0' (0 Padding) Conversion 'd' Integer, 'f' Float, 't' date, 'T' Time

Binärdarstellung

Siehe

Integer.toBinaryString(number);
Long.toBinaryString(number);
Long.toBinaryString(Double.doubleToRawLongBits(number));

Java Properties

Über Properties kann man leicht Parameter zur Konfiguration einer Anwendungen setzen und lesen (ähnlich dem setzen einer Systemvariable wie z.B. PATH). So kann man in Java leicht Properties auslesen

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

...

 // System properties (java -Dvariable=value)
 Properties systemProperties=System.getProperties();

 // Properties found in a file in the classpath, will also
 // contain the values from the system properties
 Properties fileProperties  =new Properties(systemProperties);
 URL url =  ClassLoader.getSystemResource("MyProperties.properties");
 fileProperties.load(new FileInputStream(new File(url.getFile())));

 // Properties we will fill with the code during runtime
 // will also contain the file properties (and with them also
 // the system properties)
 Properties extraProperties =new Properties(fileProperties);      

 // changes to the top level properties objects ...
 systemProperties.setProperty("test.helloworld", "Hello world");
 // ... are also reflected in their children
 String message=extraProperties.getProperty("test.helloworld");
 // debug output
 extraProperties.list(System.out);

Java Preferences

Über Preferences kann man leicht Userbezogene Einstellungen abspeichern und später wieder laden. Dabei werden die Information im Hintergrund automatisch an einem zentralen Ort (pro User) abgelegt. Unter Windows z.B. in der Registry,

HKEY_CURRENT_USERSoftwareJavaSoftPrefs

man selbst muss sich um den Ablageort nicht kümmern.

Preferences prefsRoot = java.util.prefs.Preferences.userRoot().node("de.tgunkel.Java.Demo.Preferences");

// read the already stored values
String  name    =prefsRoot.get(       "name",     "unknown");
Double  weight  =prefsRoot.getDouble( "weight",   0.0);
Boolean selected=prefsRoot.getBoolean("selected", false);
Long    id=      prefsRoot.getLong(   "id", 0L);

// store new values
prefsRoot.put       ("name",      "John Doe");
prefsRoot.putDouble ("weight",    90.01);
prefsRoot.putBoolean("selected",  true);
prefsRoot.putLong   ("id",        1234567L);

JMX

jconsole

Speichermodell in Java

Stack: Die lokalen und primitiven Variablen einer Methode werden im Stack gespeichert. Heap: Neu erzeugte Objekte landen im Eden Space / "young generation". Objekte dort werden statistisch oft erzeugt und schnell wieder aufgegeben. Nach einem Garbage Collector Lauf wandern alle Objekte, die ihn überlegt haben in den Survivor Space. Nach einigen Durchläufen landen die überlegebenden Objekte dann in der Tenured Generation / old generation. Das Verschieben der Objekte kostet zwar Aufwand, dafür können dabei aber wieder zusammenhänge Speicherbereiche entstehen. Non-heap memory: Thread übergreifender Speicher welchen die Java VM für interne Zwecke benötigt. Z.B. Informationen pro Klasse, Methode, Konstruktoren, aber auch Konstanten. Wird Permanent Generation genannt, obwohl der Speicher nicht permant sein muss. Hinzu kommt noch der Code Cache.

GUI mit Java

Swing

Java in Internetseiten

Java Applet

Java wird beim Client ausgeführt Sun Java Applet Tutorial

import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet
{
 private static final long serialVersionUID = 1L;

 public void init() {};

 public void start() {};       
 public void stop() {};

 public void paint(Graphics g)
 {
  g.drawRect(20, 20, getSize().width - 40, getSize().height - 40);
  g.drawString("Hello world!", 40, 40);
 }

 public void destroy() {};

}

Wird so in HTML eingebettet

<applet width=300 height=300 code="HelloWorld.class"> </applet>

JavaServer Pages und Servlets

Java wird auf dem Server ausgeführt JavaServer Pages und Servlets

Verteilte Programmierung mit RMI und WebServices

Verteilte Programmierung mit RMI und WebServices

Bound Properties / PropertyChangeListener

Bound Properties

Man möchte Code ausführen, wann immer sich in einer anderen Klasse (einer Bean) ein bestimmtes Attribut ändert. Dazu nimmt man sich die ganz normale Bean Klasse mit ihren Settern und Gettern. Die Klasse wird um ein PropertyChangeSupport Attribut ergänzt und in allen betroffenen Settern wird über diese Attribut in jedem relevanten Setter ein firePropertyChange ausgeführt. Außerdem wird noch die Möglichkeit geschaffen, dass man von außen einen PropertyChangeListener in dem PropertyChangeSupport Attribut registrieren kann.

public class MyBean
{
 private Long    id;
 private String  name;
 private Integer age;

 private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport( this );

 public void addPropertyChangeListener( PropertyChangeListener listener )
 {
  this.myPropertyChangeSupport.addPropertyChangeListener( listener );
 }

 public void removePropertyChangeListener( PropertyChangeListener listener )
 {
  this.myPropertyChangeSupport.removePropertyChangeListener( listener );
 }

 public Long getId()
 {
  return id;
 }
 public void setId(Long pId)
 {
  this.id = pId;
 }

 public String getName()
 {
  return name;
 }
 public void setName(String pName)
 {
  String lOldName=this.name;
  this.name = pName;
  this.myPropertyChangeSupport.firePropertyChange("name", lOldName, this.name);
 }

 public Integer getAge()
 {
  return age;
 }
 public void setAge(Integer pAge)
 {
  Integer lOldAge=this.age;
  this.age = pAge;
  this.myPropertyChangeSupport.firePropertyChange("age", lOldAge, this.age);
 }
}

So sieht z.B. ein PropertyChangeListener aus, der nur ermittelt, wie das Attribut hieß, dass geändert wurde.

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class AttributeStalker implements PropertyChangeListener
{
        @Override
        public void propertyChange(PropertyChangeEvent evt)
        {
                String attributeName=evt.getPropertyName();
                ...
        }
}

Und so benutzt man die Bean mit dem PropertyChangeListener

MyBean b=new MyBean();
AttributeStalker s=new AttributeStalker();
b.addPropertyChangeListener(s);
b.setId(5l);
b.setName("Foo");

Java SSL

Der Inhalt der keystore Datei auflisten

# keytool.exe -list -keystore my_keystore
Enter keystore password: ********
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
XXXX, 18.03.2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX

Ein jar mit jarsigner auf valide Signaturen überprüfen

# jarsigner.exe -verbose -certs  -verify myfile.jar

CORBA

JavaCorba

Quartz

JavaQuartz

Java 7

Was ist eigentlich neu in Java 7?

Lesbare Konstanten

Konstanten können mit _ lesbarer gemacht werden und es ist möglich Binärkonstanten zu verwenden:

// make constant more readable
int one_million = 1_000_000;
int oneMillion  =   1000000;
boolean equal=(one_million==oneMillion);

// add a binary constant 0b ...
int binaryNine=0b1001;
int nine=9;
boolean equal=(nine==binaryNine);

Switch mit Strings

In einem Switchblock können Strings verwendet werden

final String JOHN="john";
String result="String switch says the user is ";

switch(aString)
{
    case "Foo":
        result+="Mr. Foo";
        break;
    case "Bar":
        result+="Mr. Bar";
        break;
    case JOHN:
        result="John";
        break;
    default:
        result="a surprise";
}

Diamond Operator

Es ist nicht mehr notwendig, den Datentyp bei der Instanziierung zu wiederholen

// pre Java 1.7
HashMap<Integer, String> prejva17=new HashMap<Integer, String>();

// Java 1.7
HashMap<Integer, String> products=new HashMap<>();
products.put(123456, "Gigant TV");
products.put(1,      "DVD");

Mehr als eine Exception fangen

Man kann jetzt mehr als eine Exception auf einmal fangen und bearbeiten

try
{
    if(bang==0)
    {
        throw new IllegalArgumentException();
    }
    else
    {
        throw new IllegalStateException();
    }
}
// catch more than one exception at once
catch(IllegalArgumentException | IllegalStateException e)
{
    System.out.println("got exception "+e);
}

Ressourcen Management

Bisher war es recht aufwendig mit Ressourcen umzugehen, die auch wieder geschlossen werden müssen

// the pre Java 1.7 way
FileOutputStream fos=null;
try
{
    fos=new FileOutputStream(filename);
    // ...
}
catch (FileNotFoundException e)
{
    e.printStackTrace();
    // ...
    throw new RuntimeException(e);
}      
/* You needed a finally block to make sure your closeable resource
 * is closed under all circumstances
 */
     
finally
{
    try
    {
        if(fos!=null) fos.close();
    } catch (IOException e)
    {
        e.printStackTrace();
        // ...
        throw new RuntimeException(e);
    }
}

Jetzt können dieses Ressourcen automatisch geschlossen werden, wenn sie java.io.Closeable implementieren und innerhalb eines try Statements definiert und erzeugt werden:

/* a variable of a (sub) type of Closeable
 * inside a try will automatically issue close()
 * when the variable reaches its end of lifetime.
 * Don't forget that even the implicit close()
 * may issue an exception
 */

try(Closeable fos=new FileOutputStream(filename))
{
    // ...
}
catch (IOException e) {
    e.printStackTrace();
    // ...
    throw new RuntimeException(e);
}

Java 7 Links

Java 8

Was ist eigentlich neu in Java 8?

Java8Streams

Date

Java 8 Date Time

Annotations

Eine Annotation darf jetzt mehrfach gesetzt werden

@Foo("Value1")
@Foo("Value2")
class Person {}

Die Annotation dazu sieht so aus

@Repeatable(ContainerForAllFoos.class)
@interface Foo {
    String value();
}

Und hier werden dann bei Mehrfachnutzung die Einzelwerte abgelegt

@interface ContainerForAllFoos {
    Foo[] value();
}

Nullpointer

Angenommen man hat eine Klasse die eine Liste von Freunden beinhaltet, und jeder Freund hat wiederum einen Namen. Man kann also z.B. so auf einen Namen zugreifen

friendsHolder.allFriends.get(0).getName().length();

Allerdings kann es dabei an mehreren Stellen zu einer NullPointerException kommen, was aufwendige Tests darauf notwendig machen kann

if(friendsHolder!=null &&
   friendsHolder.allFriends!=null &&
   friendsHolder.allFriends.get(0)!=null &&
   friendsHolder.allFriends.get(0).getName()!=null) {  
}

So funktioniert das mit der neuen Optional Klasse

Optional.ofNullable(friendsHolder)
        .flatMap(a -> Optional.ofNullable(a.allFriends))
        .flatMap(b -> Optional.ofNullable(b.get(0)))
        .flatMap(c -> Optional.ofNullable(c.getName()))
        .ifPresent(System.out::println);

Concurrency Java 8

Concurrency Java 8

Nashorn JavaScript Engine for the JVM

Nashorn: A Next-Generation JavaScript Engine for the JVM

Other new Java 8 Features

Java 8 new features

Tools for Java development

JavaTools

Software für Android entwickeln

Android