java -Xmx512m
java -version:1.4
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
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
Ein Interface, darf nur abstrakte Methoden und Konstanten enthalten
/**
* My Interface
*/
package mypackage;
/**
* @author John Doe
*
*/
public interface MyInterface
{
/**
* @param number The number which is added
* @return The new sum
*/
public double add(final int number);
/**
* The limit for the result after the mathematical operations
*/
final static double maxValue=10000;
}
Eine abtrakte Klasse, enthält mindestens eine abstrakte Methode
/**
* An abstract class which will be used for things which are
* not allowed in an Interface
*/package mypackage;
/**
* @author John Doe
*
*/
public abstract class MyAbstractClass
{
/**
* Constructor
*/
public MyAbstractClass()
{
this.value=0;
}
/**
* This is the current value which will be modified by the
* mathematical operations which are offered
*/
protected double value;
}
Eine normale Klasse, darf höchsten von einer anderen Klasse erben, aber von beliebig vielen Interfaces implementieren.
/**
* This class shows that you can implement multiple Interfaces
*/
package mypackage;
/**
* @author John Doe
*
*/
public class MyClass extends MyAbstractClass
implements MyInterface, MyOtherInterface
{
/* (non-Javadoc)
* @see mypackage.MyInterface#add(int)
*/
public double add(final int number)
{
System.out.println("The maxvalue is " + AdderInterface.maxValue);
double res=this.value+=number;
this.value=res;
return res;
}
}
| Type | Größe | Von bis |
| boolean | 1 | |
| char | 2 | |
| byte | 1 | -128...127 |
| short | 2 | -32768...32767 |
| int | 4 | -2147483648 ... 2147483647 |
| long | 8 | -9223372036854775808...9223372036854775807 |
| float | 4 | 1,40239846 * 10^-45 ... 3,40282347 * 10^38 |
| double | 8 | 4,94065645841246544 * 10^-324 ... 1,79769131486231570 * 10^308 |
int i = 4711;
Integer j = i; // j = Integer.valueOf(i)
int k = j; // k = j.intValue()
String str = "HELLO WORLD";
b = ( str instanceof String ); // (1)
b = ( str instanceof Object ); // (2)
b = ( str instanceof Foo ); // (3)
(1) und (2) sind beide wahr, (3) nicht
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).
Kurzschreibweise für bedingte Zuweisung
//if(ungerade) max=l; else max=l-1;
int max=(ungerade) ? l : l-1;
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
int i[]; // == int [] i;
Foo[] x;
int i[][]; // == int [][] i == int[] i[]
int[] i, x[], y; // == int [] i; int [][]x; int[] y;
int[] prim = { 5, 7, 7 + 4, };
Array mit vorgegebener Größe:
// int hundredElements[ 100 ]; <-- ERROR
int[] hundredElements;
hunderdElements = new int[ 100 ];
int[] prim;
prim = new int[]{ 5, 7, 11, };
System.out.println( hunderedElements.length );
Rechteckiges Array
int i[][]=new int[3][4];
Beliebiges mehrdimensionales Array
int i[][]=new int[3][];
i[0]=new int[7];
i[1]=new int[19];
i[2]=new int[2];
i[3]=new int[100];
foo( new double[]{ 1.1, 2,5, 3.2 } );
double sum = 0;
double[] myarray;
List<Double> mylist=new LinkedList<Double>();
// (1)
for ( int i = 0; i < myarray.length; i++ )
{
sum += myarray[i];
}
// (1b)
for ( double n : mylist )
{
sum += n;
}
// (2)
for (ListIterator<Double> i = mylist.listIterator(); i.hasNext(); )
{
sum+=i.next();
}
// (2b)
for ( double n : myarray )
{
sum += n;
}
(1) Normaler Array Durchlauf
(1b) Kurzschreibweise für (1)
(2) Durchlauf eines Containers mit einem Iterator
(2b) Kurzschreibweise für (2). Man verliert aber den Vorteil gegebenfalls einen Iterator zur Hand zu haben (z.B. zum Löschen von Elementen).
Unnötige Methodenaufrufe in for Schleifen sparen
Häufig sehen for Schleifen so aus
for(int a=0; a<getMaxA(); a++)
Wenn sich der Rückgabewerte der Methode aber für die Dauer des Schleifendurchlaufes nicht ändert und die Methode eine nennenswerte Laufzeit hat, kann man die Schleife über eine weitere Variable deutlich beschleunigen
for(int a, int b=getMaxFoo();
a<b;
a++);
static void arraycopy( Object src, int srcPos, Object dest, int destPos, int length );
int[] y = Arrays.copyOfRange( x, 6, 9 );
So kann man einen String Array in einen String Vector wandeln
String [] myArray;
...
Vector<String> myVector = new Vector<String>(Arrays.asList(myArray));
Arrays.equals( a1, a2 ) ); // (1)
Arrays.deepEquals( a1, a2 ); // (2)
// (1) Referenzen der Elemente im Array müssen gleich sein
// (2) Inhalt muss gleich sein // (2)
Methoden können eine undefinierte Anzahl an Parametern erwarten, ansprechbar wie ein Array
int max( int... x)
{
System.out.println(x.lenght);
}
Foo x,y;
x=new Foo();
y=x.clone();
Flache Kopie von Objekten erzeugen:
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
public enum Weekday
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Der Zugriff erfolgt so:
Weekday.MONDAY
In den case Statements einer switch Anweisung dagegen so:
MONDAY
Über Enums kann man iterieren
for (Tag tag:Weekday.values()) { }
Optional erklären dass man eine Methode des Vaters überschreibt (Fehler falls nicht)
@Override
public void foo( int alter )
Anderen Konstruktor der eigenen Klasse aufrufen
this(5);
muss die erste Anweisung des Konstruktors sein, keine Objektvariablen übergebbar
Wenn man eine Klasse hat, von der es nur wenige Ausprägungen gibt, wie z.B. Boolean.
Dann macht es oft keinen Sinn, dass man mit new beliebig viele verschiedene Objekte dieser Klasse erzeugen kann. Eine besser Variante ist es dann, statt einem Konstruktor eine valueOf() Methode anzubieten
public static valueOf(boolean b)
Diese liefert dann immer wieder die wenigen Objekte zurück die es geben kann, hier z.B. entweder Boolean.TRUE oder Boolean.FALSE. Es darf dann natürlich keine Methode geben, ob den Wert eines solchen Objektes zu verändern, weil sonst auch alle anderen Nutzer dieses Objektes davon betroffen wären.
Initialisieren von Variablen in allen Konstruktoren
class Foo
{
int j=1; // (1)
Foo()
{
this.k=0;
}
Foo( int i )
{
this.k = j;
}
}
entspricht
class Foo
{
int j; // (1)
Foo()
{
this.j=1; // (1)
this.k=0;
}
Foo( int i )
{
this.j = 1; // (1)
this.k = i;
}
}
Bei statischen Variablen
public class Foo
{
static int x = 2;
}
entspricht
public class InitStaticVariable
{
static int x;
static
{
x = 2;
}
}
Konstruktor des Vaters aufrufen
super(5);
Methode des Vaters aufrufen
@Override
public void foo( int alter ) {
super.foo();
...
}
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();
}
class Foo
{
class Bar
{
}
}
Zum Erzeugen eines Objekts der inneren Klasse, braucht man ein Objekt der äußeren Klasse. Versucht man z.B. in einer statischen Methode der äußeren Klasse ein Objekt der inneren Klasse zu erzeugen würde das fehlschlagen
No enclosing instance of type foo is accessible. Must qualify the allocation with an enclosing instance of type foo (e.g. x.new Bar() where x is an instance of foo).
Nur innere Klassen dürfen Private oder Protected sein. Wenn sie es sind, hat es Einfluss darauf, wer sie benutzen darf.
public class Foo
{
static String s = "HELLO WORLD";
int i = 1;
static class Bar
{
void test()
{
System.out.println(s);
// System.out.println( i ); // (1)
}
}
}
Mitglieds- oder Elementklassen
public class Foo
{
String s = "Hello World";
class Bar
{
void test1()
{
System.out.println( s );
}
//static void test2() { } // (2)
}
}
Von aussen erzeugen
Foo a = new Foo();
Bar b = a.new Bar();
public class Foo
{
public static void main( String[] args )
{
int i = 1;
final int j = 2;
class Bar
{
Bar() {
System.out.println( j );
//System.out.println( i ); // (3) Fehler, da i nicht final
}
}
new Bar();
}
}
Anonyme innere Klassen erben entweder von einer anderen Klasse oder implementieren eine Schnittstelle
class Foo()
{
// ...
}
interface Bar()
{
// ...
}
class Blub{}
{
new Foo()
{
...
}
new Bar()
{
...
}
}
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> T myMethod( T a, T b )
{
//...
}
}
Wenn man Comparable implementiert ist es oft sehr störend, dass man dann als Parameter jede beliebige andere Klasse akzeptieren muss. So kann man es nur für eine Bestimmte Klasse implementieren
public class Foo implements Comparable<Foo>
{
public int compareTo(Foo pOther)
{
}
}
/**
* @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;
}
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
public class ClubException extends RuntimeException
{
public ClubException()
{
}
public ClubException( String s )
{
super( s );
}
}
kill -3 PID
jstack PID;
Thread.dumpStack();
Sicherstellen dass die gegebene Bedingung erfüllt ist
assert(i>0);
Überwachung der Assertions aktivieren
java -enableassertions foo
java -enableassertions:bar foo
Von der Klasse
Thread
erben und die Methode run überschreiben.
public class Foo extends Thread
{
@Override
public void run()
{
// ...
}
}
Jetzt einfach ein Objekt dieser Klasse erzeugen und die Methode
start()
und nicht
run()
aufrufen.
final int nrOfThreads=4;
Foo [] f=new Foo[nrOfThreads];
for(int i=0; i<nrOfThreads; i++)
{
f[i]=new Foo();
f[i].start();
}
Das Interface
Runnable
implementieren
public class Bar implements Runnable
{
public void run()
{
// ...
}
}
final int nrOfThreads=4;
Thread [] f=new Thread[nrOfThreads];
for(int i=0; i<nrOfThreads; i++)
{
f[i]=new Thread(new Bar());
f[i].start();
}
try
{
for(int i=0; i<nrOfThreads; i++) f[i].join();
}
catch (InterruptedException e) {};
Normalerweise läuft ein Programm so lange weiter, bis auch der letzte Thread sich beendet hat. Ruft man auf einem Thread die Methode
setDaemon(true);
auf, wird auf das Ende dieses Threads nicht mehr gewartet.
Um einen Thread von außen beenden zu können, ist es hilfreich, wenn dieser auf
!isInterrupted()
testet und
InterruptedException
Exceptions fängt und dann selbst
interrrupt()
aufruft. Z.B.
while (!isInterrupted())
{
try
{
...
}
catch ( InterruptedException e )
{
interrupt();
}
}
Jetzt kann man den Thread von außen mit
interrupt()
beenden.
Methode darf nur von einem Thread gleichzeitig betreten werden
public class Foo
{
synchronized public static void bar()
{
// ...
}
}
Pro Objekt darf Methode nur von einem Thread gleichzeitig betreten werden
public class Foo
{
synchronized public void bar()
{
// ...
}
}
Entspricht
public class Foo
{
public void bar()
{
synchronized(this)
{
// ...
}
}
}
Alternative:
lock.lock();
// ...
lock.unlock();
Variablen auf die nur der entsprechenden Thread Zugriff hat (auf private Attribute hätte alle Objekte der entsprechenden Klasse Zugriff).
ThreadLocal foo = new ThreadLocal()
{
protected int bar()
{
return 5;
}
};
Entweder für beliebige Objekte
Collection c = new LinkedList();
c.add("Hello");
c.add("World");
for ( Object x : c ) System.out.println( x );
Oder für spezielle
Collection<String> c = new LinkedList<String>();
for ( String x : c ) System.out.println( x );
ArrayList, LinkedList
HashSet, TreeSet, LinkedHashSet
HashMap, TreeMap, LinkedHashMap, WeakHashMap
- man hat ein Object O
- und einen Key K
- Von dem Key K gibt es ein H(K)
Die HashMap fügt im Hash dann unter H(K) alle Objekte O ein. Es kann mehrere Objekte O geben, die den gleichen Wert für H(K) haben, aber unterschiedliche Werte für K. Ist auch K gleich, wird der vorherige Eintrag überschrieben.
Für die Klasse Integer gilt z.B. H(K)=K, das muss aber nicht so sein.
LinkedList, ArrayBlockingQueue, PriorityQueue
So kann man eine Collection sortieren lassen:
List<Foo> myList;
Collections.sort(myList);
Comparator myComparator=new MyFooComparator();
Collections.sort(myList, myComparator);
Im ersten Fall muss Foo Comparable implementieren, im zweiten Fall kann man seine(n) eigenen Comparator(en) schreiben.
Die Sortierung arbeitet direkt auf dem Container selbst, gegenfalls vorher klonen.
Bei Sortieren kann man leicht das Problem bekommen, dass man zwei Elemente a, b hat, die nicht gleich sind (!a.equals(b)). Allerdings könnten beide Objekte bezüglich einer Sortierung weder kleiner noch größer sein. Beispielsweise bei der Sortierung von Personen nach Schuhgröße. a und b können ganz verschiedene Menschen sein und dennoch genau die selbe Schuhegröße haben. In diesem Fall muss man besonders mit einem TreeSet Container aufpassen. Dieser speichert jedes Objekt höchstens ein mal und aus a.compareTo(b)==0 schließt er (fälschlicherweise?) nur eines der beiden Objekte muss im Container gespeichert werden. Lösung: compareTo() auf mehr Attribute ansetzten oder statt TreeSet eine andere Datenstruktur benutzen (TreeBag?)
Dateien und Verzeichnisse
Zahlreiche Methoden der Date Objekte sind seit einiger Zeit deprecated. Mit der Hilfe der Calendar Klasse kann man weiterhin auf die entsprechenden Datumsfelder zugreifen:
Date lCurrentDate=new Date();
Calendar lCal=Calendar.getInstance();
lCal.setTime(lCurrentDate);
lCal.get(Calendar.YEAR);
lCal.get(Calendar.MONTH);
lCal.get(Calendar.DAY_OF_MONTH);
Und entsprechend lässt sich das Datum auch manipulieren
Calendar lToday = new GregorianCalendar();
lToday.set(Calendar.HOUR_OF_DAY, 23);
lToday.set(Calendar.MINUTE, 59);
lToday.set(Calendar.MINUTE, 0);
lToday.set(Calendar.SECOND, 0);
lToday.set(Calendar.MILLISECOND, 0);
Date lNewDate=lToday.getTime();
Möchte man von einem gegeben Datum einige Tage abziehen oder addieren geht das so
Calendar calendar = new GregorianCalendar();
calendar.add(Calendar.DAY_OF_MONTH, -14);
Date lNewDate=calendar.getTime();
Class c=null;
try
{
c = Class.forName("foo");
} catch (ClassNotFoundException ex)
{
// ...
}
Nützliche Java Komponenten
Apache Commons.
ToStringBuilder
ToStringBuilder.reflectionToString(this);
new ToStringBuilder(this).append("Name: ", name).append("ID: ", id).toString();
Mit
one-jar kann man mehrere jars in ein großes jar packen und über one-jar selbststartend machen.
Mit dem
JAD Java Decompiler aus class-Dateien wieder lesbaren Quellcode machen. Mit dem Eclipse Plugin
JADClipse sogar vollautomatisch öffnen der entsprechenden Klassen.
Integer.parseInt("042", 10);
Ein BigDecimal erzeugen
BigDecimal x=new BigDecimal("1.123456789");
Ein BigDecimal runden
BigDecimal y=x.setScale(2, BigDecimal.ROUND_HALF_UP);
(x bleibt dabei unverändert)
Mit BigDecimal teilen
BigDecimal a=new BigDecimal("1").setScale(0);
BigDecimal b=new BigDecimal("1.2345");
BigDecimal r=a.divide(b, RoundingMode.HALF_UP);
Achtung, die Genauigkeit beim Teilen zweier BigDecimal wird durch das Objekt festgelegt, dessen divide Methode aufgerufen wird. Das kann zu überraschenden Ergebnissen führen! Daher überlegen, die Genauigkeit beim Teilen anzugeben
BigDecimal r=a.divide(b, 7, RoundingMode.HALF_UP);
Gibt man beim teilen zweier BigDecimal Zahlen keine Roundsart an, und passt das Ergebnis nicht in ein BigDecimal (z.B. 1/3), gibt es eine Exception
java.lang.ArithmeticException: Non-terminating decimal expansion; noexact representable decimal result.
Deshalb beim Teilen immer eine Rundungsart angeben!
jconsole
jvisualvm
Als erstes den Heap Speicher hochsetzen
-Xmx512m
Falls das nicht hilft, aktuellen heap Speicherverbrauch des Programms mit der genannten PID ausgeben
jmap -histo PID
Oder aber abwarten bis es nicht mehr gereicht hat und dann erst auswerten
# java -XX:+HeapDumpOnOutOfMemoryError -jar foo.jar
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid29731.hprof ...
Heap dump file created [1271286324 bytes in 143.266 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
...
Und die Datei dann auswerten
jhat -J-Xmx512m java_pid29731.hprof
...
Started HTTP server on port 7000
22-08-2010 14.12