Java

Klassen


Unterprogramme, Methoden

Unterprogramme sind Prozeduren und Funktionen, in Java werden sie als Methoden bezeichnet.

   void prozedur( parameter ) block;

   typ funktion( parameter ) {
    ...
       return (typ) wert;
    ...
   }

   typ methode( typ_1 name_1, ..., typ_n name_n ) {
    ...
        int x = (int)name_1;
        int y = funktion( name_2, 4711 ); 
        int z = name_3 + name_n; 
   ...
   }

   public static void main(String[] args) { 
     // die Hauptprozedur, 
     // d.h. die erste die ausgefhrt wird
   }

Beispiele:

public class Unterprogramme {

    void prozedur() {
    }

    int funktion() {
	return 4711;
    }

    int quadrat(int a) {
	return a*a;
    }

    double quadrat(double a) {
	return a*a;
    }

    int name(int a) {
	int b = quadrat( 2 );
	return b+a;
    }

    long fakultaet(long n) {
	if ( n <= 1l ) {
           return 1l;
	} else {
	   return n * fakultaet( n-1l);
	}
    }

    double summe(double[] a) {
	double sum = 0.0;
	for ( int i = 0; i < a.length; i++ ) {
	    sum += a[i];
	}
	return sum;
    }

   void main() { 
       prozedur();
       int n = funktion();
       int i = quadrat(n); 
       int j = name( 3 );
       long k = fakultaet( 10 );
       double[] z = { 1.0, 1.2, 3.2, 4.6, 9.2 };
       double s = summe( z );

       System.out.println("n = " + n);
       System.out.println("i = " + i);
       System.out.println("j = " + j);
       System.out.println("k = " + k);
       System.out.println("s = " + s);
   }

   public static void main(String[] args) { 
       // die Hauptprozedur, 
       (new Unterprogramme()).main();
   }
}
public class Ueberladen {

    void problem(int a, long b) { }

    void problem(long a, long b) { }

    void problem(long a, int b) { }

    void ratemal() {
	problem( 1, 2L ); // ok
	problem( 1L, 2 ); // ok
	problem( 1, 2 );  // fehler
    }

    long problem(long a, long b) { // fehler
	return a*b;
    }
}
public class Uebergabe {

    class Unter {
	int a = 0;
	int b = 1;
    }

    void wert( int c ) {
	c = c + 55;
    }

    void referenz( Unter u ) {
	int x = u.a * 3;
	u.b = x + 14;
    }

    void unveraendert( Unter u ) {
        u = new Unter();
	int x = u.a * 3;
	u.b = x + 14;
    }

    void ratemal() {
	int w = 3;
	wert( w );
	// w == 3

	Unter u = new Unter();
	referenz( u );
	// u.a == 0
	// u.b == 14

	unveraendert( u );
	// u.a == 0
	// u.b == 1
    }

}
public class Rekursion {

    long fakultaet(int n) {
	if ( n <= 1 ) {
           return 1l;
	} else {
	   return n * fakultaet( n-1);
	}
    }

    double summe(double[] a) {
	double sum = 0.0;
	for ( int i = 0; i < a.length; i++ ) {
	    sum += a[i];
	}
	return sum;
    }

    double reksumme(double[] a) {
	return reksumme(a,a.length);
    }

    double reksumme(double[] a, int n) {
        if ( n == 0 ) return 0.0;
	return reksumme(a,n-1) + a[n-1];
    }

    long potenz(int b, int e) { // berechne b hoch e
	// if ( e < 0 ) { b = 1/b; e = -e; }
	if ( e == 0 ) return 1l;
        if ( e == 1 ) return (long)b;
        return b * potenz( b, e-1 );
    }

    long quadrat(long b) { // berechne b*b
	return b*b;
    }

    long potenzFast(int b, int e) { // berechne b hoch e
	// if ( e < 0 ) { b = 1/b; e = -e; }
	if ( e == 0 ) return 1l;
        if ( e == 1 ) return (long)b;
        if ( e % 2 == 0 ) 
           return quadrat( potenzFast( b, e/2 ) );
        return b * potenzFast( b, e-1 );
    }

    void main() { 
       long k = fakultaet( 10 );
       double[] z = { 1.0, 1.2, 3.2, 4.6, 9.2 };
       double s = summe( z );
       double r = reksumme( z );
       long p = potenz( 10, 15 );
       long f = potenzFast( 10, 15 );

       System.out.println("k = " + k);
       System.out.println("s = " + s);
       System.out.println("r = " + r);
       System.out.println("p = " + p);
       System.out.println("f = " + f);
    }

   public static void main(String[] args) { 
       // die Hauptprozedur, 
       (new Rekursion()).main();
   }
}
public class Summe {

    static double[] betrag = null;

    static double summe() {
        double s = 0.0;
        for (int i = 0; i < betrag.length; i++ ) {
	    s += betrag[i];
	}
        return s;
    }


    public static void main(String[] args) {
	betrag = new double[args.length];
	for (int i = 0; i < args.length; i++) {
	    betrag[i] = 0.0;
	    try {
	    betrag[i] = Double.parseDouble( args[i] );
	    // betrag[i] = Double.valueOf( args[i] ).doubleValue();
	    } catch (NumberFormatException e) { }
	}

        System.out.println("Eingegeben wurden " + args.length + " Zahlen");
        double s = summe();
        System.out.println("Die Summe ist " + s);
    }
}

Klassen und Objekte

Klassen bieten die Zusammenfassung von Funktionen, Prozeduren und Variablen zu einem bestimmten Zweck. (Abstraktion von einzelnen Methoden zu Modulen oder Gruppen.)

public class Klassen {

    static int klassen = 0;

    int meineNummer = 0;

    Klassen() {
	meineNummer = klassen++;
    }

    static String statistik() {
	return "Erzeugte Klassen = " + klassen;
    }

    public String toString() {
	return "Meine Nummer = " + meineNummer + " von " + klassen;
    }

    public static void main(String[] args) {
	System.out.println( Klassen.statistik() );
	Klassen einz = new Klassen();
	Klassen zwei = new Klassen();
	Klassen drei = new Klassen();
	Klassen vier = new Klassen();
	Klassen fuenf = new Klassen();
	System.out.println( statistik() );

	System.out.println("einz: " + einz.toString());
	System.out.println("zwei: " + zwei);
	System.out.println("vier: " + vier);
	System.out.println("drei: " + drei);
	System.out.println("fuenf: " + fuenf);
    }
}

Java-Programme werden mittels Klassen definiert. Jede öffentliche (d.h. als public deklarierte) Klasse muß in einer separaten Datei gespeichert werden. Der Name der Datei muß mit dem Namen der public-Klasse übereinstimmen (z.B. muß die Klasse public class Test in der Datei Test.java gespeichert werden).

Der Speicherbereich für das Objekt wird automatisch allokiert. Wenn das Objekt nicht mehr gebraucht wird (d.h. keine Variable referenziert mehr das Objekt), wird der Speicherbereich während eines Garbage-Collection-Vorganges wieder freigegeben (Speicherrecycling). Das heißt, daß im Gegensatz zu C/C++ kein expliziter `delete'-Operator benötigt wird.

In Java k”nnen Prozeduren nur innerhalb von Klassen definiert werden. Prozeduren k”nnen zu einer Klasse oder zu Objekten der Kasse geh”ren. Es gibt in Java keine globalen Variablen oder Methoden.

   public class Card {
     int number;
     static int base = 5;
     public static String version = "1.0";
   
     public Card(int n) {
       number = n;
     }
   
     public int getNumber() {
       return number;
     }
   
     public static int getBase() {
       return base;
     }
   
     public int getDiff() {
       return number - base;
     }
   
     public static void main(String[] args) {
       Card c = new Card(7);
   
       System.out.println(c.version+":"+
              c.getNumber()+"-"+c.getDiff()+"="+
              Card.getBase());
     }
   }

Die Ausgabe dieses Programms ist 1.0:7-2=5.

Parameterbergabe von Referenzen

Die šbergabe von Objektrefrenzen erm”glicht die Ver„nderung von bergebenen Objekten in der aufrufenden Methode.

public class Confuse {

    static class Reference {
	int val;
    }

    public int confuse( int a, int b ) {
        a = 1; 
        a = b + a;
	return a;
    }

    public Integer confuse( Integer a, Integer b ) {
        a = new Integer(1); 
        a = new Integer( b.intValue() + a.intValue() );
	return a;
    }

    public Reference confuse( Reference a, Reference b ) {
        a.val = 1; 
        a.val = b.val + a.val;
	return a;
    }

    public static void main(String[] args) {
	Confuse c = new Confuse();

	int m = 4;
	int n = c.confuse( m, m );
	System.out.println("m = " + m);
	System.out.println("n = " + n);

	Integer i = new Integer(4);
	Integer j = c.confuse( i, i );
	System.out.println("i = " + i);
	System.out.println("j = " + j);

	Reference k = new Reference();
        k.val = 4;
	Reference l = c.confuse( k, k );
	System.out.println("k = " + k.val );
	System.out.println("l = " + l.val );

    }
}

Das Problem kann durch Zugriffskontrolle gel”st werden.

Kapselung und Zugriffskontrolle

Klassen bzw. Objekte k”nnen ihre Variablen und Methoden in verschiedenen Abstufungen kapseln (einschliessen). Dabei werden nur die Variablen oder Methoden nach aussen, d.h. fr andere Objekte sichtbar gemacht, die notwendig sind. Man spricht auch vom Geheimnisprinzip. Die ”ffentlich zug„nglichen Variablen und Methoden werden meist noch durch Interfaces (s.u.) definiert. Vorteil: die Interna k”nnen beliebig modifiziert werden solange die Schnittstelle und deren Semantik erhalten bleibt.

Java unterschiedet public, private, protected und default Zugriffsrechte.

Beispiele siehe Abschnitt "Sichtbarkeit".

Der Kontrakt zwischen dem/der Entwicklerin einer Klasse und einem Anwender besteht aus der Syntax und Semantik der Aufrufschnittstelle.

Konstruktoren

Konstruktoren dienen der Initialisierung der Objekt-Variablen. Klassen-Variablen werden ein einziges mal vor der ersten Verwendung der Klasse initialisiert.

Beispiel fr einen neuen Datentyp

Wir entwickeln eine Klasse Complex, die fr die Arithmetik komplexer Zahlen verwendet werden kann.

Der Konstruktor soll aus einem Paar reeler Zahlen (a,b) eine komplexe Zahl a + i b machen.

Methoden und Konstanten:

/**
 * Klasse zum Rechnen mit Komplexen Zahlen
 * hk, 9.12.2001
 *
 **/

public class Complex {

    /* Die Datenstruktur */

    private double re;  // der Realteil
    private double im;  // der Imagin„rteil


    /* Die Konstruktoren erzeugen aus einem Paar von 
       double Zahlen eine Komplexe Zahl */

    public Complex(double r, double i) {
        re = r;
        im = i;
    }

    public Complex(double r) {
        this(r,0.0);
    }

    public Complex() {
        this(0.0);
    }


    /* Konstanten: 1, 0 und i */

    public static final Complex ZERO = new Complex();

    public static final Complex ONE = new Complex(1.0);

    public static final Complex I = new Complex(0.0,1.0);


    /* Bestimmen des Real- und Imagin„r-Teils */

    public double reTeil() { return re; }

    public double imTeil() { return im; }


    /* Darstellung als Zeichenkette */

    public String toString() {
        String s = "" + re;
        if ( im < 0 ) s += " - " + (-im) + "i";
           else s += " + " + im + "i";
        return s;
    }


    /* Vergleich zweier Komplexer Zahlen */

    public boolean equals(Complex b) {
	return ( re == b.reTeil() && im == b.imTeil() );
    }


    /* Arithmetische Operationen: +, -, - */

    public Complex add(Complex b) {
	return new Complex(re + b.reTeil(), im + b.imTeil());
    }

    public Complex subtract(Complex b) {
	return new Complex(re - b.reTeil(), im - b.imTeil());
    }

    public Complex negate() {
	return new Complex(-re,-im);
    }


    /* Arithmetische Operationen: Konjugierte, Absolut Betrag */

    public Complex conjugate() {
	return new Complex(re,-im);
    }

    public double abs() {
	return ( re * re + im * im );
    }


    /* Arithmetische Operationen: *, Inverse, / */

    public Complex multiply(Complex b) {
	return new Complex(re * b.reTeil() - im * b.imTeil(),
                           re * b.imTeil() + im * b.reTeil() );
    }

    public Complex inverse() {
        double a = this.abs();
	return new Complex(re/a, -im/a); // Konjugierte
    }

    public Complex divide (Complex b) {
	return this.multiply( b.inverse() );
    }
}

Anwendungsbeispiel

/**
 * Testen der Klasse zum Rechnen mit Komplexen Zahlen
 * hk, 9.12.2001
 *
 **/

public class ComplexTest {

    public static void main(String[] args) {

        Complex a = new Complex(2.0,3.0);
        System.out.println("a(2,3) = " + a);

        System.out.println("Null(0,0) = " + Complex.ZERO);
        System.out.println("Eins(1,0) = " + Complex.ONE);

        Complex b = Complex.ONE;
        b = b.add(a);
        System.out.println("b(3,3) = " + b);

        Complex c = new Complex(3.0,3.0);
        System.out.println("c(3,3) = " + c);
        boolean t = c.equals(b);
        System.out.println("t(true) = " + t);

        Complex d = c.conjugate();
        System.out.println("d(3,-3) = " + d);

        double e = c.abs();
        System.out.println("e(18) = " + e);

        Complex f = c.multiply(d);
        System.out.println("f(18,0) = " + f);

        // c*conjugate(c) = abs(c)
        t = e == f.reTeil();
        System.out.println("t(true) = " + t);

        // i*i = -1
        Complex g = Complex.I.multiply(Complex.I);
        System.out.println("g(-1,0) = " + g);

        // 1/i = -i
        Complex h = Complex.ONE.divide(Complex.I);
        System.out.println("h(0,-i) = " + h);


    }
}

Vererbung

Wir definieren eine einfache Klasse für Autos (Car). Man kann mit dieser Klasse ein Auto mit den Parametern Modell (model), Baujahr (year) und (Neu-)Preis (price) definieren.

Die Klassen-Methoden getModel(), getYear() und getPrice() dienen dem Zugriff auf die Klassen-Parameter.

public class Car {
  String model;
  int year;
  int price;

  public Car(String m, int y, int p) {
    model = m;
    year = y;
    price = p;
  }

  public String getName() {
    return model+" [year="+year+"]";
  }

  public int getPrice() {
    return price;
  }

  public static void main(String[] args) {
    Car ford = new Car("ford bronco", 1992, 35000);
    Car vw   = new Car("vw golf", 1984, 25000);

    System.out.println(
       ford.getName()+" costs "+ford.getPrice());
    System.out.println(
       vw.getName()+" costs "+vw.getPrice());
  }
}

Mit dieser Klasse kann man zum Beispiel die Objekte ford und vw erzeugen. Dies ergibt dann folgende Ausgabe.

    ford bronco [year=1992] costs 35000
    vw golf [year=1984] costs 25000

Mit dem Schlüsselwort extends kann man eine Klasse von einer anderen Klasse ableiten. Als Beispiel einer abgeleiteten Klasse von Car sei die Klasse Gebrauchtwagen (UsedCar) definiert, die den zusätzlichen Parameter `gefahrene Kilometer' (mileage) hat.

public class UsedCar extends Car {
  int mileage;

  public UsedCar(String m, int y, int p, int k) {
    super(m, y, p);
    mileage = k;
  }

  public String getName() {
    return super.getName()+" (mileage="+mileage+")";
  }

  public int getMileage() {
    return mileage;
  }

  public int getPrice() {
    return 10000*price/(mileage+10000);
  }
}

Die Methode getMilage() dient wieder dem Zugriff auf die Klassen-Parameter. Der Konstruktor für UsedCar ruft mit super(m, y, p) den Konstruktor der Basisklasse auf, dann wird der Parameter mileage gesetzt. Die Methode getPrice() überschreibt die Methode mit dem gleichen Namen und der gleichen Signatur (d.h. der gleichen Art und Anzahl der Parameter) von der Basisklasse. getPrice() berechnet in dieser Klasse den Gebrauchtwagenpreis in Abhängigkeit von der gefahrenen Kilometerzahl.

Mit diesen Klassen kann man dann zum Beispiel in dem Hauptprogramm main die folgenden Beziehungen definieren und ausdrucken.

  public static void main(String[] args) {
    Car cars[] = new Car[4];
    cars[0] = new Car("ford bronco", 1992, 35000);
    cars[1] = new UsedCar("ford bronco", 1992, 
                          35000, 8000);
    cars[2] = new Car("vw golf", 1984, 25000);
    cars[3] = new UsedCar("vw golf", 1984, 
                          25000, 20000);

    for (int i=0; i<4; i++)
      System.out.println(cars[i].getName()
             +" costs "+cars[i].getPrice());
  }

Als Ausgabe erhält man zum Beispiel.

   java UsedCar

   ford bronco [year=1992] costs 35000
   ford bronco [year=1992] (mileage=8000) costs 19444
   vw golf [year=1984] costs 25000
   vw golf [year=1984] (mileage=20000) costs 8333

Interface

Eine Java-Klasse ist nur von einer anderen Klasse ableitbar. Java kennt keine Mehrfachvererbung! Aber mit dem Sprachkonstrukt interface kann eine Klasse mehrere Methodensignaturen erben. Ein Interface deklariert nur abstrakte Methoden.

Zum Beispiel kann man ein Interface Rank definieren, das das Vergleichen zweier Objekte erlaubt. compare() gibt eine positive ganze Zahl zurück, falls dieses Objekt (this) in der implementierten Ordnung vor dem anderen Objekt (obj) steht.

  public interface Rank {
    public int compare(Rank obj) 
           throws RankException;
  }

Ist die implementierte Ordnung nicht total, so wird für unvergleichbare Objekte eine RankException ausgelöst.

  public class RankException 
         extends RuntimeException {
  }

Eine Subklasse von Rectangle (aus java.awt), die dieses Interface unterstützt, kann man wie folgt definieren.

  public class RankedRect extends Rect implements Rank {
    public RankedRect(int w, int h) {
      super(w,h);
    }

    public int compare(Rank obj) 
           throws RankException {
      try {
        return area() - ((Rect)obj).area();
      }
      catch (ClassCastException e) {
        throw new RankException();
      }
    }
  }

In einer ähnlichen Weise kann man eine Subklasse von Car definieren.

  public class RankedCar extends Car implements Rank {
    public RankedCar(String m, int y, int p) {
      super(m,y,p);
    }

    public int compare(Rank obj) {
      try {
        return getPrice()-((Car)obj).getPrice();
      }
      catch (ClassCastException e) {
        throw new RankException();
      }
    }
  }

Diese beiden Klassen können behandelt werden, als ob sie vom Typ Rank wären. Zum Beispiel als Argument in einer Methode foo(Rank obj). Eine Klasse kann mehrere Interfaces implementieren. Bei der Erzeugung von Objekten von Klassen, die ein Interface implementieren, kann man die Struktur, die nicht von dem Interface stammt, ignorieren.

   Rank r = new RankedCar(model, year, price);

Dann ist aber nur noch die Verwendung der Methode r.compare(.) möglich und nicht mehr r.getModel(). Um dennoch getModel() zu verwenden, muß erst ein Cast (eine Typenanpassung)   auf RankedCar gemacht werden:

   ( (RankedCar) r ).getModel()

Abstrakte Klassen

Man kann eine Klasse definieren, die keine vollständige Implementierung der deklarierten Methoden enthält.

Diese kann man sich als Mischform zwischen einem Interface und einer richtigen Klasse vorstellen. Ein Teil der Methoden wird implementiert, und für einen anderen Teil der Methoden werden nur die Spezifikationen (das Interface) festgelegt.

Eine solche Klasse wird als abstrakte Klasse bezeichnet und muß mit dem Schlüsselwort abstract gekennzeichnet werden.

  public abstract class Cell {
      int size;
     
      public int getSize() {
             return size;
      }
     
      public abstract void interact(Cell neighbor);
  }

Aus abstrakten Klassen können k”nnen keine Objekte erzeugt werden. Aus einer Subklasse, die die fehlenden Implementationen definiert, k”nnen Objekte erzeugt werden.

Beispiel: BitString

Interface: BitStringInterface

Methoden: toString() und toBitString() liefern die entsprechende Darstellung als Bin„rfolge.

public interface BitStringInterface {

    public String toString(); 

    public String toBitString();

}

Abstrakte Klasse: AbstractBitString

Methoden: toString() wird mit Hilfe von toBitString() implementiert.

public abstract class AbstractBitString 
                implements BitStringInterface {

    public String toString() {
	return toBitString();
    }
 
    public abstract String toBitString();

}

Klasse: BitStringSign

Darstellung von ganzen Zahlen als Bin„rfolge. Die Zahlen werden als Paare von Vorzeichen und positiven Zahlen dargestellt.

Konstruktoren: fr byte, short, int und long,

Methoden: toBitString() liefert Zeichenkette entsprechend dem Datentyp.
bitStringSign() liefert Zeichenkette entsprechend der 'Vorzeichen, Gr”sse'-Darstellung.

public class BitStringSign extends AbstractBitString {

    private int art;
    final static int BYTE  = 1;
    final static int SHORT = 2;
    final static int INT   = 3;
    final static int LONG  = 4;

    final static byte BYTEsize  =  7;
    final static byte SHORTsize = 15;
    final static byte INTsize   = 31;
    final static byte LONGsize  = 63;

    private long ls = 0;

    public BitStringSign(byte b) {
        art = BYTE;
	ls = b;
    }

    public BitStringSign(short s) {
        art = SHORT;
	ls = s;
    }

    public BitStringSign(int s) {
        art = INT;
	ls = s;
    }

    public BitStringSign(long s) {
        art = LONG;
	ls = s;
    }

    public String toBitString() {
        switch (art) {
          case  BYTE: return bitStringSign(BYTEsize,ls);
          case SHORT: return bitStringSign(SHORTsize,ls);
          case   INT: return bitStringSign(INTsize,ls);
          case  LONG: return bitStringSign(LONGsize,ls);
	     default: return ""+ls;
	}
    }

    public static String bitStringSign(byte l, long b) {
        String e = "";
        long x = 0;
        String s = "";
        long zwei = (long)2;

        if (b < 0 ) {
	    x = (long)-b; s = "1";
	} else {
            x = (long)b; s = "0";
	}

        for (int i = 0; i < l; i++) { 
            if ( (x % zwei) == 0 ) { e = "0" + e; }
	    else { e = "1" + e; }
            x = (long)(x >> 1);
	}

        return s+e;
    }

}

Klasse: BitStringComplement

Darstellung von ganzen Zahlen als Bin„rfolge. Die Zahlen werden im Zweier-Komplement dargestellt.

Konstruktoren: fr byte, short, int und long,

Methoden: toBitString() liefert Zeichenkette entsprechend dem Datentyp.
bitStringComplement() liefert Zeichenkette entsprechend der Komplement-Darstellung.

public class BitStringComplement extends AbstractBitString {

    private int art;
    final static int BYTE  = 1;
    final static int SHORT = 2;
    final static int INT   = 3;
    final static int LONG  = 4;

    final static byte BYTEsize  =  7;
    final static byte SHORTsize = 15;
    final static byte INTsize   = 31;
    final static byte LONGsize  = 63;

    private long ls = 0;

    public BitStringComplement(byte b) {
        art = BYTE;
	ls = b;
    }

    public BitStringComplement(short s) {
        art = SHORT;
	ls = s;
    }

    public BitStringComplement(int s) {
        art = INT;
	ls = s;
    }

    public BitStringComplement(long s) {
        art = LONG;
	ls = s;
    }

    public String toBitString() {
        switch (art) {
          case  BYTE: return bitStringComplement(BYTEsize,ls);
          case SHORT: return bitStringComplement(SHORTsize,ls);
          case   INT: return bitStringComplement(INTsize,ls);
          case  LONG: return bitStringComplement(LONGsize,ls);
	     default: return ""+ls;
	}
    }

    public static String bitStringComplement(byte l, long b) {
        String e = "";
        long x = b;
        long zwei = (long)2;

        for (int i = 0; i < l+1; i++) { 
            if ( (x % zwei) == 0 ) { e = "0" + e; }
	    else { e = "1" + e; }
            x = (long)(x >> 1);
	}

        return e;
    }

}

Klasse: BitTest

Testen der zwei Darstellungen. Es werden Objekte von BitStringSign und BitStringComplement erzeugt. Diese Objekte k”nnen in Variablen der entsprechenden Klassen abgespeichert werden, aber auch in Variablen vom Typ BitStringInterface als auch von Typ AbstractBitString.

public class BitTest {

    public static void main(String[] args) {
	test1();
	test2();
	test3();
	test4();
    }

    static void test1() {
	BitStringInterface a = new BitStringSign((int)7);
        System.out.println("a(     7) = " + a);
	BitStringInterface b = new BitStringComplement((int)7);
        System.out.println("b(     7) = " + b);

	BitStringInterface c = new BitStringComplement((short)32767);
        System.out.println("c( 32767) = " + c);
	BitStringInterface d = new BitStringSign((short)32767);
        System.out.println("d( 32767) = " + d);

	AbstractBitString e = new BitStringSign((int)-32767);
        System.out.println("e(-32767) = " + e);
	AbstractBitString f = new BitStringComplement((int)-32767);
        System.out.println("f(-32767) = " + f);

        System.out.println();
    }

    static void test2() {
        short x = -1;
        for (byte l = 0; l <= 15; l++ ) {
            BitStringInterface g = new BitStringSign((short)x);
            System.out.println("g( "+ x + ") = " + g);
	    x *= (short)2;
	}
        System.out.println();
    }

    static void test3() {
        short x = -1;
        for (byte l = 0; l <= 15; l++ ) {
            AbstractBitString h = new BitStringComplement((short)x);
            System.out.println("h( "+ x + ") = " + h);
	    x *= (short)2;
	}
        System.out.println();
    }

    static void test4() {
        short x = -1;
        for (byte l = 0; l <= 15; l++ ) {
	    System.out.println("i( "+ x + ") = " + Integer.toBinaryString(x));
	    x *= (short)2;
	}
        System.out.println();
    }
}

Im letzten Test erfolgt ein Vergleich mit der 'eingebauten'ÿ Funktion Integer.toBinaryString(x))

Ausgabe:

a(     7) = 00000000000000000000000000000111
b(     7) = 00000000000000000000000000000111
c( 32767) = 0111111111111111
d( 32767) = 0111111111111111
e(-32767) = 10000000000000000111111111111111
f(-32767) = 11111111111111111000000000000001

g( -1) = 1000000000000001
g( -2) = 1000000000000010
g( -4) = 1000000000000100
g( -8) = 1000000000001000
g( -16) = 1000000000010000
g( -32) = 1000000000100000
g( -64) = 1000000001000000
g( -128) = 1000000010000000
g( -256) = 1000000100000000
g( -512) = 1000001000000000
g( -1024) = 1000010000000000
g( -2048) = 1000100000000000
g( -4096) = 1001000000000000
g( -8192) = 1010000000000000
g( -16384) = 1100000000000000
g( -32768) = 1000000000000000

h( -1) = 1111111111111111
h( -2) = 1111111111111110
h( -4) = 1111111111111100
h( -8) = 1111111111111000
h( -16) = 1111111111110000
h( -32) = 1111111111100000
h( -64) = 1111111111000000
h( -128) = 1111111110000000
h( -256) = 1111111100000000
h( -512) = 1111111000000000
h( -1024) = 1111110000000000
h( -2048) = 1111100000000000
h( -4096) = 1111000000000000
h( -8192) = 1110000000000000
h( -16384) = 1100000000000000
h( -32768) = 1000000000000000

i( -1) = 11111111111111111111111111111111
i( -2) = 11111111111111111111111111111110
i( -4) = 11111111111111111111111111111100
i( -8) = 11111111111111111111111111111000
i( -16) = 11111111111111111111111111110000
i( -32) = 11111111111111111111111111100000
i( -64) = 11111111111111111111111111000000
i( -128) = 11111111111111111111111110000000
i( -256) = 11111111111111111111111100000000
i( -512) = 11111111111111111111111000000000
i( -1024) = 11111111111111111111110000000000
i( -2048) = 11111111111111111111100000000000
i( -4096) = 11111111111111111111000000000000
i( -8192) = 11111111111111111110000000000000
i( -16384) = 11111111111111111100000000000000
i( -32768) = 11111111111111111000000000000000

Vergleiche auch die Hll-Klassen java.lang.Integer und java.lang.Long. Fr die Klassen java.lang.Byte und java.lang.Short existieren keine vergleichbaren Methoden.


© Universität Mannheim, Rechenzentrum, 1998-2002.

Heinz Kredel
Last modified: Sun Dec 8 15:57:42 CET 2002