
public  class MyFiniteStack {

/*--------------------------------
 * Klassen- und Objektattribute
 *--------------------------------*/

    // Feld-Variablen als Klassenattribute: 
    // 'static' Feld-Variablen sind
    // auf Klassenebene allokiert und für alle
    // Objektinstanzen nur einmal vorhanden.
    static final int defaultStackSize = 10;
   
    // Anzahl momentan allokierter Stacks
    public static int numberOfAllStacks = 0;

    // Summe der Stackelemente, über alle existierenden
    // Stack-Instanzen gebildet
    public static int numberOfAllStackElements = 0;

    // Feld-Variablen, die in jedem Objekt lokal allokiert
    // werden (Objektattribute):

    // Anzahl der Elemente im Stack
    int numberOfMyStackElements;
    
    // Array zum Verweis auf zum Stack gehoerige Elemente
    Object myStackArray[];

    // Tatsaechliche Groesse des Stacks (entweder Default-Groesse
    // defaultStackSize oder Nutzer-definierte Groesse)
    int myStackSize;

/*---------------------------------------------------------------------
 * Methoden
 *--------------------------------------------------------------------*/

    /*---
     *--- Konstruktoren - beachte: keine Rueckgabewerte
     *---*/
    public MyFiniteStack() {

        // Stack-Array allokieren
// Im Array myStackArray werden REFERENZEN auf die
// im Stack zu verwaltenden Objekte gespeichert
        myStackArray = new Object[defaultStackSize];
        // tasaechliche Stack-Groesse definieren
        myStackSize = defaultStackSize;
        // Anzahlfeld initialisieren
        numberOfMyStackElements = 0;
        // Anzahl existierender Stacks inkrementieren
        numberOfAllStacks++;

 
    }

    // Ueberladen (Overloading) des Konstruktors:
    public MyFiniteStack(int specialStacksize) {

        // Stack-Array allokieren
        myStackArray = new Object[specialStacksize];
        // tasaechliche Stack-Groesse definieren
        myStackSize = specialStacksize;
        // Anzahlfeld initialisieren
        numberOfMyStackElements = 0;
        // Anzahl existierender Stacks inkrementieren
        numberOfAllStacks++;
 
    }

   
    /*---
     *--- Finalizer: Operation, die automatisch von der
     *--- Garbage Collection aufgerufen wird, wenn das
     *--- Objekt zerstoert wird.
     *---*/
    protected void finalize() {
	// Anzahl existierender Stacks dekrementieren
        System.out.println("finalize()-Aufruf");
        numberOfAllStacks--;
    }

    /*---
     *--- Oeffentliche  Methoden
     *---*/

    public String toString() {
        // Hier wird die toString() Methode aus Object ueberladen
        return "This is a MyFiniteStack-object at address "
	    + super.toString() +":\n";

    }

    public void push(Object obj) throws MyFiniteStackException {

        //System.out.println("push called");

	if ( numberOfMyStackElements < myStackSize ) {
	    myStackArray[ numberOfMyStackElements++ ] = obj;
	}
        else {
	    throw new 
             MyFiniteStackException(numberOfMyStackElements);
	}
    }

    public Object pop() throws MyFiniteStackException  {

        //System.out.println("pop called");

	if ( 0 < numberOfMyStackElements ) {
	    return myStackArray[--numberOfMyStackElements];
        }
        else {
           throw new MyFiniteStackException(numberOfMyStackElements);
	}
              
    }


    public Object peek() {

        //System.out.println("peek called");

        return ( 0 < numberOfMyStackElements ) 
                  ? myStackArray[numberOfMyStackElements-1]
	    : null;
    }



  
    /*---
     *--- nicht oeffentlich zugaengliche Methoden
     *---*/

    
  
}

