21_BackReference

Code-Dateien

DateinameAktion
CODECode_ClassRoom.zipDownload
CODECode_Fenster.zipDownload
CODECode_Student.zipDownload
CODECode_Urlaub.zipDownload

PDF-Dokumente

DateinameAktion
PDFFolie_ClassRoom.pdfÖffnen
PDFFolie_Student.pdfÖffnen
PDFFolie_Urlaub.pdfÖffnen
PDFUebung_Computer.pdfÖffnen
PDFUebung_Labor.pdfÖffnen
PDFUebung_Wohnung.pdfÖffnen

Videos

DateinameAktion
VIDEOVideo_ClassRoom_EAbspielen
VIDEOVideo_Fenster_Teil1_DAbspielen
VIDEOVideo_Fenster_Teil2_DAbspielen
VIDEOVideo_Fenster_Teil3_DAbspielen
VIDEOVideo_Student_DAbspielen
VIDEOVideo_Urlaub_DAbspielen

Lernmaterialien

Assoziation

001.png

Die bisherige aufnehmen Methode prüft weder:

  • Student schon in dieser Schule angemeldet ist noch

  • Student schon in einer anderen Schule angemeldet ist.

    public void aufnehmen(Student wer)
    {
        if (student0 == null)
        {
            student0 = wer;
        }
        else
        {
            if (student1 == null)
            {
                student1 = wer;
            }
            else
            {
                if (student2 == null)
                {
                    student2 = wer;
                }
                else
                {
                    System.out.println("Fehler: kein Platz!");
                }
            }
        }
    }

backreference - aufnehmen

Student

Beim Aufnehmen werden 2 Referenzen gesetzt:

  • Schule => Student … sitzt am Sessel (schon implementiert)

  • Student => Schule … geht in die Schule

Beim Student wird eine neue Eigenschaft hinzugefügt:

public class Student
{
    private String  name;
    private int     alter;
    private boolean matura;
    private School  school;   // **NEW** backreference

Durch die neue Eigenschaft benötigen wir:

    public void setSchool(School school)
    {
        this.school = school;
    }

    public School getSchool()
    {
        return school;
    }

School

References

Ausgangssituation:

002.png

Beide Referenzen sind null.

student0 = wer;       // reference
wer.setSchool(this);  // backreference

Ergebnis:

003.png

Check

004.png

"Hans" besucht schon eine Schule =>

"Susi" besucht keine Schule null

Ein Student darf sich nur dann anmleden, wenn er noch keine Schule besucht!

        if (wer.getSchool() == null)
        {
            ...
        }
        else
        {
            System.out.println("Fehler: schon in einer Schule!");
        }

null

Eine Methode, die sich als Parameter eine Objektreferenz erwartet kann zwei Werte übergeben bekommen:

  • Objectreference

  • null

007.png

Beim Methodenaufruf von null.getSchool() liefer Java eine NullPointerException. Von einer null Referenz kann keine Methode aufgerufen werden!

006.png

Somit muss die Parameterprüfung auf null durchgeführt werden!

    public void aufnehmen(Student wer)
    {
        if (wer != null)
        {
            ...
        }
        else
        {
            System.out.println("Fehler: kein Student!");
        }
    }

Lösung

    public void aufnehmen(Student wer)
    {
        if (wer != null)
        {
            if (wer.getSchool() == null)
            {
                if (student0 == null)
                {
                    student0 = wer;
                    wer.setSchool(this);
                }
                else
                {
                    if (student1 == null)
                    {
                        student1 = wer;
                        wer.setSchool(this);
                    }
                    else
                    {
                        if (student2 == null)
                        {
                            student2 = wer;
                            wer.setSchool(this);
                        }
                        else
                        {
                            System.out.println("Fehler: kein Platz!");
                        }
                    }
                }
            }
            else
            {
                System.out.println("Fehler: schon in einer Schule!");
            }
        }
        else
        {
            System.out.println("Fehler: kein Student!");
        }
    }
005.png

Test

null

htl.aufnehmen(null)

Erwartetes Ergebnis:

  • Fehlermeldung

  • htl.anzahlStudent() == 0

School.java

    public int anzahlStudent()
    {
        int anz=0;

        if (student0 != null)
        {
            anz++;
        }
        if (student1 != null)
        {
            anz++;
        }
        if (student2 != null)
        {
            anz++;
        }
        return anz;
    }

SchoolTest.java

    @Test
    public void testAufnehmenNull()
    {
        School htl;

        htl = new School("HTL");
        htl.aufnehmen(null);
        //Fehler
        assertEquals(0, htl.anzahlStudent());
    }

OK

SchoolTest.java

    @Test
    public void testAufnehmenOK()
    {
        School htl;
        Student max, susi;

        htl = new School("HTL");
        max = new Student("Max", 21, true);
        susi = new Student("Susi", 19, false);
        htl.aufnehmen(max);
        assertEquals(1, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(null, susi.getSchool());
        htl.aufnehmen(susi);
        assertEquals(2, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
    }
008.png

2* selben Schule

    @Test
    public void testAufnehmen2xHtl()
    {
        School htl;
        Student max;

        htl = new School("HTL");
        max = new Student("Max", 21, true);
        htl.aufnehmen(max);
        assertEquals(1, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        htl.aufnehmen(max);
        //Fehler
        assertEquals(1, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
    }
009.png

aufnehmen in htl und hak

    @Test
    public void testAufnehmenHtlHak()
    {
        School htl, hak;
        Student max;

        htl = new School("HTL");
        hak = new School("HAK");
        max = new Student("Max", 21, true);
        htl.aufnehmen(max);
        assertEquals(1, htl.anzahlStudent());
        assertEquals(0, hak.anzahlStudent());
        assertEquals(htl, max.getSchool());
        hak.aufnehmen(max);
        //Fehler
        assertEquals(1, htl.anzahlStudent());
        assertEquals(0, hak.anzahlStudent());
        assertEquals(htl, max.getSchool());
    }
010.png

backreference - abmelden

Ausgangslage:

011.png

Ergebnis:

012.png
    public void abmelden(Student wer)
    {
        if (wer != null)
        {
            if (wer.getSchool() == this)
            {
                if (student0 == wer)
                {
                    student0 = null;
                    wer.setSchool(null);
                }
                else
                {
                    if (student1 == wer)
                    {
                        student1 = null;
                        wer.setSchool(null);
                    }
                    else
                    {
                        if (student2 == wer)
                        {
                            student2 = null;
                            wer.setSchool(null);
                        }
                        else
                        {
                            System.out.println("Fehler: kann nicht sein!");
                        }
                    }
                }
            }
            else
            {
                System.out.println("Fehler: Student geht nicht in diese Schule!");
            }
        }
        else
        {
            System.out.println("Fehler: kein Student!");
        }
    }

public void abmelden(Student wer)

Die Methode abmelden bekommt eine Objektreferenz wer übergeben.

if (wer != null)

Prüft, ob eine gültige Objektreferenz übergeben wurde. Damit wird eine NullPointerException vermieden.

if (wer.getSchool() == this)

wer Objektreferenz von Student (möchte sich abmelden)

this Objektreferenz von School (ich = meine Schule)

Es wird geprüft, ob der Student auch in der richtigen Schule sitzt.

if (student0 == wer)

Sitzt der Student wer am Sessel 0 student0.

student0 = null;

Löschen der Referenz (Assoziation)

Der Sessel 0 wird frei null

wer.setSchool(null);

Löscht die backreference

Der Student geht in keine Schule mehr.

Test

null

    @Test
    public void testAbmeldenNull()
    {
        School htl;        
        htl = new School("HTL");
        htl.abmelden(null);
        //Fehler
        assertEquals(0, htl.anzahlStudent());
    }

abmelden sessel0

    public void testAbmeldenSessel0()
    {
        School htl;        
        Student max, susi, alex;

        htl = new School("HTL");
        max  = new Student("Max",  21, true);
        susi = new Student("Susi", 19, true);
        alex = new Student("Alex", 20, true);
        htl.aufnehmen(max);
        htl.aufnehmen(susi);
        htl.aufnehmen(alex);
        assertEquals(3, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
        htl.abmelden(max);
        assertEquals(2, htl.anzahlStudent());
        assertEquals(null, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
    }

abmelden sessel1

    @Test
    public void testAbmeldenSessel1()
    {
        School htl;        
        Student max, susi, alex;

        htl = new School("HTL");
        max  = new Student("Max",  21, true);
        susi = new Student("Susi", 19, true);
        alex = new Student("Alex", 20, true);
        htl.aufnehmen(max);
        htl.aufnehmen(susi);
        htl.aufnehmen(alex);
        assertEquals(3, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
        htl.abmelden(susi);
        assertEquals(2, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(null, susi.getSchool());
        assertEquals(htl, alex.getSchool());
    }

abmelden sessel2

    @Test
    public void testAbmeldenSessel2()
    {
        School htl;        
        Student max, susi, alex;

        htl = new School("HTL");
        max  = new Student("Max",  21, true);
        susi = new Student("Susi", 19, true);
        alex = new Student("Alex", 20, true);
        htl.aufnehmen(max);
        htl.aufnehmen(susi);
        htl.aufnehmen(alex);
        assertEquals(3, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
        htl.abmelden(alex);
        assertEquals(2, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(null, alex.getSchool());
    }

abmelden nicht in der Schule

    @Test
    public void testAbmeldenAndereSchule()
    {
        School htl, hak;
        Student max, susi, alex;

        htl = new School("HTL");
        hak = new School("HAK");
        max  = new Student("Max",  21, true);
        susi = new Student("Susi", 19, true);
        alex = new Student("Alex", 20, true);
        htl.aufnehmen(max);
        htl.aufnehmen(susi);
        htl.aufnehmen(alex);
        assertEquals(3, htl.anzahlStudent());
        assertEquals(0, hak.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
        hak.abmelden(alex);
        //Fehler
        assertEquals(3, htl.anzahlStudent());
        assertEquals(htl, max.getSchool());
        assertEquals(htl, susi.getSchool());
        assertEquals(htl, alex.getSchool());
    }

backreference tauschen

013.png

Bleistift Ausgangslage

GELB Ergebnis

public class Student
{
    ...

    public void tauschen(Student wer)
    {

    }

    ...
}

Die Methode tasuchen vertauscht die beiden Objketreferenzen this mit wer. <=>

Algorithmus:

  • thisSchool merken

  • werSchool merken

  • this abmelden

  • wer abmelden

  • thisSchool meldet sich wer an

  • werSchool meldet sich this an

Der Basisalgorithmus ist wie folgt:

    public void tauschen(Student wer)
    {
        School thisSchool = this.getSchool();
        School werSchool = wer.getSchool();
        thisSchool.abmelden(this);
        werSchool.abmelden(wer);
        thisSchool.anmelden(wer);
        werSchool.anmelden(this);
    }

Parameterprüfung:

  • wer != null … anderenfalls kein Methodenaufruf möglich

  • this.getSchool() != nullthis muss in eine Schule gehen

  • wer.getSchool() != nullwer muss in eine Schule gehen

  • this.getSchool() != wer.getSchool()this und wer müssen in unterschiedliche Schulen gehen

public void tauschen(Student wer)
{
    if (wer != null)
    {
        if (this.getSchool() != null)
        {
            if (wer.getSchool() != null)
            {
                if (this.getSchool() != wer.getSchool())
                {
                    School thisSchool = this.getSchool();
                    School werSchool = wer.getSchool();
                    thisSchool.abmelden(this);
                    werSchool.abmelden(wer);
                    thisSchool.aufnehmen(wer);
                    werSchool.anmelden(this);
                }
                else
                {
                    System.out.println("Fehler: gleiche Schule!");                            
                }
            }
            else
            {
                System.out.println("Fehler: " + wer.getName() + " ohne Schule");        
            }
        }
        else
        {
            System.out.println("Fehler: " + this.getName() + " ohne Schule");    
        }
    }
    else
    {
        System.out.println("Fehler: kein Student!");
    }
}

Test: