6.8 Lösungen

6.8.1 Referenzieren, Derefenzieren und GC

Klasse Main

Das folgende Programm wird wie folgt gestartet

java s1.block6.Main 3 gc

Es erwartet zwei Kommandozeilenargumente. Das erste Argument beschreibt die Anzahl der zu erzeugenden Generationen.

Das zweite Argument is optional. Steht hier GC wird eine System Garbarge Collection angestoßen

package block6.gc;

public class Main {

    /**
    * Auslesen von Systemparametern
    */
    public static void systemStatus(){
        Runtime r = Runtime.getRuntime();
        System.out.println("*** System Status ***");
        System.out.println("Prozessoren :       " + r.availableProcessors());
        System.out.println("Freier Speicher:    " + r.freeMemory());
        System.out.println("Maximaler Speicher: " + r.maxMemory());
        System.out.println("Gesamter Speicher:  " + r.totalMemory());
        System.out.println("***  ***");
    }

    public static void main(String[] args) {
        int vorfahren = 0;
        boolean systemCollection=false;
        Person p1;

        systemStatus();
        // Parsen des ersten Arguments
        // Diese Zeichenkette enthält die ANzahl der Generationen
        if (args.length > 0 ) { // Gibt es ein erstes Argument?
        try { vorfahren = Integer.parseInt(args[0]);}
        catch (NumberFormatException e) {
            System.err.println("Argument muss Ganzzahl sein");
            System.exit(1);
            }
        }
        // Auslesen des zweiten Arguments
        // Steht hier die Zeichenkette GC in Klein- oder Grossschreibung
        if (args.length > 1 ) // Gibt es ein zweites Argument
            systemCollection = ((args[1].equalsIgnoreCase("gc"));

        p1 = new Person(vorfahren);
        //p1 = null;
        System.out.println();
        System.out.println("Erster Schritt erledigt: " + Person.zaehler +
                " Instanzen erzeugt");
        systemStatus();
        if (systemCollection)  {
            System.out.println("Starte System GC");
            System.gc();
        }
        p1 = new Person(vorfahren);
        System.out.println();
        System.out.println("Zweiter Schritt erledigt: " + Person.zaehler +
                " Instanzen erzeugt");
        systemStatus();
    }

}

Klasse Person

package s1.block6;
public class Person {
    Person vater;
    Person mutter;
    static int zaehler=0;

    public Person (int vorfahren)
    {
        if ( vorfahren>0) {
            vater = new Person(vorfahren-1);
            mutter = new Person(vorfahren-1);
        }
        zaehler++;
        if (zaehler%1000 == 0) System.out.print(".");

    }
}

6.8.2 "Copy Constructor" Klasse

Klasse Main

package s1.block6;

public class Main {

    public static void systemStatus(){
        Runtime r = Runtime.getRuntime();
        System.out.println("*** System Status ***");
        System.out.println("Prozessoren :       " + r.availableProcessors());
        System.out.println("Freier Speicher:    " + r.freeMemory());
        System.out.println("Maximaler Speicher: " + r.maxMemory());
        System.out.println("Gesamter Speicher:  " + r.totalMemory());
        System.out.println("***  ***");
    }

    public static void main(String[] args) {
        int vorfahren = 0;
        boolean systemCollection=false;
        Person p1;

        systemStatus();
        if (args.length > 0 ) {
        try { vorfahren   = Integer.parseInt(args[0]);}
        catch (NumberFormatException e) {
            System.err.println("Argument muss Ganzzahl sein");
            System.exit(1);
            }
        }
        if (args.length > 1 )
            systemCollection = (args[1].equalsIgnoreCase("gc"));

        p1 = new Person(vorfahren);
        //p1 = null;
        System.out.println();
        System.out.println("Erster Schritt erledigt: " + Person.zaehler +
                " Instanzen erzeugt");
        systemStatus();
        if (systemCollection)  {
            System.out.println("Starte System GC");
            System.gc();
        }
        p1 = new Person(p1);
        System.out.println();
        System.out.println("Zweiter Schritt erledigt: " + Person.zaehler +
                " Instanzen erzeugt");
        systemStatus();
    }

}

Klasse Adresse

package s1.block6;

public class Adresse {
    public String ort;
    public String plz;
    public String strasse;
    public String hausnr;

    public Adresse (String o, String p, String s, String h){
        ort     = o;
        plz     = p;
        strasse = s;
        hausnr  = h;
    }

    public Adresse (Adresse orig) {
        ort     = orig.ort;
        plz     = orig.plz;
        strasse = orig.strasse;
        hausnr  = orig.hausnr;
    }
}

Klasse Person

package s1.block6;
public class Person {
    Person vater;
    Person mutter;
    String name;
    Adresse wohnort;
    static int zaehler=0;

    public Person (int vorfahren)
    {
        if ( vorfahren>0) {
            vater  = new Person(vorfahren-1);
            mutter = new Person(vorfahren-1);
        }
        wohnort = new Adresse("Berlin", "10117","Platz der Republik","1");
        name = "John Doe";
        zaehler++;
        if (zaehler%1000 == 0) System.out.print(".");
    }

    public Person (Person orig) {
         if (orig.vater != null) vater  = new Person(orig.vater);
         if (orig.mutter != null) mutter = new Person(orig.mutter);
         if (orig.wohnort != null) wohnort = new Adresse(orig.wohnort);
         name   = orig.name;
         zaehler++;
         if (zaehler%1000 == 0) System.out.print(".");
    }
}

Optional: "Copy Constructor mit begrenzter Kopiertiefe

    public Person (Person orig, int vorfahren) {
        if (vorfahren > 0) {
            if (orig.vater != null)
                vater  = new Person(orig.vater,  vorfahren-1);
            if (orig.mutter != null)
                mutter = new Person(orig.mutter, vorfahren-1);
            }
        if (orig.wohnort != null) wohnort = new Adresse(orig.wohnort);
        name   = orig.name;
        zaehler++;
        if (zaehler%1000 == 0) System.out.print(".");
    }

6.8.3 Tiefes Vergleichen Klasse Person

Klasse Person

class Person {
...
    public Person (String name1, String gort, String gplz,
            String gstrasse, String gnr){
        name = name1;
        geburtsort = new Adresse(gort,gplz,gstrasse,gnr);
        zaehler++;
        if (zaehler%1000 == 0) System.out.print(".");
   }
...
 public boolean equals(Object obj) {
         Person target;
         // Type checking is optional for this level of skills
         if (this.getClass() == obj.getClass() ) {
            target = (Person) obj;                
            return (name.equals(target.name) && 
                      (geburtsort.equals(target.geburtsort)));
            }
         else return false;
     }
...
}

Klasse Adresse

public boolean equals(Object obj) {
         Adresse target;
         // Type checking is optional for this level of skills
         if (this.getClass() == obj.getClass() ) {
            target = (Adresse) obj;                
            return (ort.equals(target.ort) && 
                plz.equals(target.plz) &&
                strasse.equals(target.strasse) &&
                hausnr.equals(target.hausnr));
            }
         else return false;
}

6.8.4 Ware/Lager Beispiel

Klasse MainLager

package s1.block6;
/**
* * Eine Hilfsklasse zur Implementierung eines Hauptprogramms
*
* @author s@scalingbits.com
* @version 1.1
*/
public class MainLager {
/*
* 5. Anlegen einer neuen Klasse MainLager * 5.1 Umkopieren der main() Methode
* aus der Klasse Lager in die Klasse MainLager.main()
*/
/*
* 8. Testen des Copy Constructors
* 8.1 Belegen Sie die ersten 500
* Lagerpositionen mit Waren
* 8.2 Klonen Sie die ersten 500 Lagerpositionen und belegen Sie die
* folgenden 500 Lagerpositionen mit Ihnen
* 8.3 Löschen Sie Ihr Lager indem Sie alle Postionen mit null belegen
* 8.4 Implementieren Sie eine Schleife die einige Minuten läuft und testen Sie
* den Speicherverbrauch mit jconsole und jps
*/

public static void main(String[] args) {
Lager lager1 = Lager.dasLager();
int position;
for (int j = 0; j < 100000; j++) {
for (int i = 0; i < 500; i++) {
position = lager1.einlagern(new Ware("Buch der Zahl " + i, 2 * i, false));
//System.out.println("Ware auf Position" + position + " eingelagert");
}
for (int i = 0; i < 500; i++) {
position = lager1.einlagern(new Ware(lager1.holen(i)));
//System.out.println("Ware auf Position" + position + " eingelagert");
}
lager1.ausraeumen();

System.out.println("Schleife " + j + " von 100000");
}
}
}

Klasse Ware

package s1.block6.loesung;
/**
* Dies ist die Dokumentation der Klasse Ware. Ware dient zum Verwalten von Gütern
* mit Preisen und Namen in einem Lager.
* @author Stefan Schneider
* @version 1.1
* @see Lager
*/
public class Ware {
/**
* Der aktuelle Mehrwertsteuersatz 2010.
* Er liegt zur Zeit bei {@value}.
*/
public static final double mws = 0.19;
private double nettoPreis; //Deklaration
public boolean halbeMws;
private String name;
public Ware empfehlung;
/**
* Konstruktor fuer die Klasse Ware
* @param n der Name der Ware
* @param np der Nettorpreis
* @param hmws halber Mehrwertsteuersatz für Ware gueltig
*/
public Ware(String n, double np, boolean hmws) {
name = n;
nettoPreis = np;
halbeMws = hmws;
}
/*
* 7. Anlegen eine Copy Constructor
* 7.1 Alle Werte des Objekts werden kopiert
* 7.2 Es wird bei Bedarf eine neue Empfehlung angelegt
*/
/**
* Copy-Konstruktor fuer die Klasse Ware
* @param w die zu klonende Ware
*/
public Ware(Ware w) {
name = w.name;
nettoPreis = w.nettoPreis;
halbeMws = w.halbeMws;
if (w.empfehlung != null)
empfehlung = new Ware(w.empfehlung);
}
/**
* Liefert den Namen einer Ware zurueck.
* @return Name der Ware
*/ public String get_name() {
return name; }
/** * Setzen eines neuen Nettopreis
* @param npr der neue Nettopreis
*/
public void set_nettoPreis(double npr) {
nettoPreis = npr;
}
/**
* Ausdrucken aller Werte auf der Konsole
*/
public void drucken() {
System.out.println("Name: " + name);
System.out.println("netto: " + nettoPreis);
System.out.println("Brutto: " + bruttoPreis());
System.out.println("Halbe Mws:" + halbeMws);
if (empfehlung != null) {
empfehlung.drucken(2);
}
}
/**
* Ausdrucken aller Werte auf der Konsole mit vorgebener Einrueckung
* für Empfehlungen
* @param einruecken eingerueckte Stellen für Empfehlungen
*/ public void drucken(int einruecken) {
String leerStellen = "";
for (int i = 0; i < einruecken; i++) {
leerStellen = leerStellen + " ";
}
System.out.println(leerStellen + "Name: " + name);
System.out.println(leerStellen + "netto: " + nettoPreis);
System.out.println(leerStellen + "Brutto: " + bruttoPreis());
System.out.println(leerStellen + "Halbe Mws:" + halbeMws);
if (empfehlung != null) {
empfehlung.drucken(einruecken + 2);
}
}
/**
* Ausgabe des Nettopreis
* @return der Nettopreis
*/ public double nettoPreis() {
return nettoPreis; }
/**
* Ausgabe des Bruttopreis
* @return der Bruttopreis
*/ public double bruttoPreis() {
double bp; //temporaere Variable; keine Klassenvariable
if (halbeMws) {
bp = Math.round(nettoPreis * (mws / 2 + 1) * 100) / 100;
} else {
bp = Math.round(nettoPreis * (mws + 1) * 100) / 100;
}
return bp;
}
}

Klasse Lager

package s1.block6;
/** * Die Klasse Lager verwaltet eine bestimmte Anzahl von Waren
* @author s@scalingbits.com
* @version 1.1
*/
public class Lager {
/*
* Aufgaben
* 1. Verwalten von n Waren in einem Feld
* 1.1 Deklarieren eines privaten Feldes
*/
private int lagerGroesse = 1000;
private Ware[] warenLager;

// 1.2 Zugriffsmethoden zum Setzen und Auslesen des Feldes
public Ware holen(int i) {
if ((i<0) || (i>=lagerGroesse)) return null;
else return warenLager[i];
} public int einlagern(Ware w) { int i=0; while ((i<lagerGroesse) && (warenLager[i] != null)) i++; if (i<lagerGroesse) { warenLager[i] = w; return i; } else return -1; } // 3. Methode zum Ausräumen des Lagers public void ausraeumen() { for (int i=0; i<lagerGroesse; i++) warenLager[i]=null; }

/*
* 2. Implementieren eines Konstruktors der das Lager
* für n Waren initialisiert
*/
private Lager() {
// Es wird ein Feld von Referenzen auf Waren angelegt
// Es werden keine Waren angelegt!
warenLager = new Ware[lagerGroesse];
}
/*
* 4. Erzeugung eines Singletons zum Erzeugen genau eines Lagers
*/
private static Lager meinLager; // Eine Objektvariable die auf das Lager zeigt
static public Lager dasLager() {
if (meinLager== null) meinLager= new Lager();
return meinLager;
}
/*
* 5. Anlegen einer neuen Klasse MainLager
* 5.1 Umkopieren der main() Methode aus der Klasse Lager in die Klasse
* MainLager.main()
*/
// 6. Testen der Factory
/*Lager lager1 = Lager.dasLager();
int position;
for (int i=0; i<500; i++)
position = lager1.einlagern(new Ware("Buch " +i, 2*i, false));
for (int i=0; i<500; i++) {
Ware w = lager1.holen(i);
System.out.println("Position " + i);
w.drucken();
}
*/
/*
* 8. Testen des Copy Constructors
* 8.1 Belegen Sie die ersten 500 Lagerpositionen mit Waren
* 8.2 Klonen Sie die ersten 500 Lagerpositionen und belegen Sie die
* folgenden 500 Lagerpositionen mit Ihnen
* 8.3 Löschen Sie Ihr Lager indem Sie alle Postionen mit null belegen
* 8.4 Implementieren Sie eine Schleife die einige Minuten läuft
* und testen Sie den Speicherverbrauch mit jconsole oder
*/
public static void main(String[] args) {
Ware ware1 = new Ware("Zeitung",12.12,true);
System.out.println("Ware1 ohne Empfehlung:");
ware1.drucken();
double p = ware1.nettoPreis();
Ware ware2 = new Ware("Potter Bd1",31.12,false);
Ware ersterBand = ware2;
ware1.empfehlung= ware2;
System.out.println("Ware1 mit Empfehlung:");
ware1.drucken();
// Erzeugen einer Ware mit 10 verketteten Empfehlungen
Ware ware3;
Ware hp1=ware2;
for (int i=2; i<= 7; i++) {
ware3 = new Ware("Potter Bd" + i,31.25+i,false);
ware2.empfehlung = ware3;
ware2 = ware3;
}
System.out.println("Alle Harry Potter Baende drucken");
hp1.drucken();
// ersterBand.drucken();
}
}