# Übergabe einer Referenz



## kodela (13. Aug 2017)

Hallo,

für ein Programm zum Erstellen und Lösen von Str8ts habe ich ein zweidimensionales Array "str8tsFld" definiert.

Ein solches Str8ts-Feld ist damit in je 9 Zeilen und Spalten unterteilt. Zu diesen 18 Bereichen kommen noch eine variable Anzahl von unterschiedlich großen Teilbereichen der Zeilen bzw. Spalten, die soganannten Str8ts. Jede Str8t kann über die Klasse STR8 beschrieben werden.

Alle Str8ts werden in der Liste "strList" zusammengefasst. Über diese Liste werden die verschiedenen Auswertemethoden aufgerufen. In den Methoden werden nun aus der Angabe zur ersten und letzten Zelle einer Str8t auch die dazwischen liegenden Zellen festgestellt und für jede Zelle ein Listeneintrag angelegt, über den die Informationen zu jeder Zelle abgefragt werden können.

Nun mein Problem: In der Liste der einzelnen Zellen wird durch die Zuweisung der Zellwert und nicht eine Referenz auf die Zelle selbst übernommen. Das bedeutet also, über einen solchen Listeneintrag kann ich zwar dessen Wert verändern. Damit verändere ich aber nicht den Wert im Str8ts-Rasterfeld. Soll der Wert direkt an der "Quelle" verändert werden, muss dies über eine direkte "Ansprache" erfolgen.

Meine Frage: Wie kann ich in der Liste der einzelnen Zellen an Stelle der Zellinhalte eine Referenz auf die jeweilige Zelle selbst aufnehmen?

Hier einige Codeschnipsel zum Verständnis meines Problems:

```
// Instanzieren des Str8ts-Rasters, der Str8ts-Liste und der Werteliste
    private final int[][] str8tsFld = new int[9][9];
    private final STR8[] strList = new STR8[50]
    private final int[] zellWert = new int[9];
  
  
    // Beispiel einer Wertzuweisung innerhalb einer Methode:
    wrt[0] = str8tsFld[str8t.ersteZelle.zl][str8t.ersteZelle.sp];
  
    // Beispiel für eine Zuweisung
    str8tsFld[str8t.letzteZelle.zl][str8t.letzteZelle.sp] = mKnd;
    str8tsFld[str8t.letzteZelle.zl][str8t.letzteZelle.sp] |= lwFlag;
    str8tsFld[str8t.letzteZelle.zl][str8t.letzteZelle.sp] |= n2;

    /**
     * Klasse für die Definition der Position einer Zelle im Str8t-Raster
     */
    private class ZELLPOS {
        int zeile;
        int spalte;
    }

    /**
     * Klasse für die Definition einer Str8t durch die Positionsangabe
     * der jeweils ersten und letzten Zelle der Str8t, deren Länge und
     * der Angabe, ob alle Zellen der Str8t gelöst sind
     */
    private class STR8 {
        ZELLPOS ersteZelle = null;
        ZELLPOS letzteZelle = null;
        int len = 0;
        boolean geloest = false;
      
        // Konstruktor
        public STR8() {
            this.ersteZelle = new ZELLPOS();
            this.letzteZelle = new ZELLPOS();
        }
    }
```
MfG, kodela


----------



## mrBrown (13. Aug 2017)

Ich würde es über eine zusätzliche Klasse `Feld` lösen, die du statt int nutzt - intern speichert Feld dann den Zustand mit einem int.


----------



## kodela (13. Aug 2017)

mrBrown hat gesagt.:


> Ich würde es über eine zusätzliche Klasse `Feld` lösen, die du statt int nutzt - intern speichert Feld dann den Zustand mit einem int.


Wie ist das gemeint, eine Klasse nur mit einem int für das Str8ts-Feld oder für eine Zelle in diesem Feld?


----------



## mrBrown (13. Aug 2017)

Für eine Zelle


----------



## kodela (13. Aug 2017)

Nein das funktioniert über eine zusätzliche Klasse bei mir nicht, hätte allerdings den Vorteil, dass man zusätzlich noch irgend welche Eigenschaften, z.B. enthält Vorgabewert, ist gelöst, mit verwalten könnte. Aber eine Referenz auf die Zelle im Str8ts-Feld (Array) bekomme ich über die zusätzliche Klasse ZELLE (so habe ich sie benannt) nicht.


----------



## mrBrown (13. Aug 2017)

Warum sollte das nicht funktionieren?


----------



## kodela (13. Aug 2017)

mrBrown hat gesagt.:


> Warum sollte das nicht funktionieren?


Wenn ich das wüsste! Ich kann nur sagen, auch wenn ich an Stelle eines "normalen" Integerwertes eine eigene Klasse mit einem Integerwert für den Inhalt einer Zelle (bitcodiert mit Vorgabewert, Lösungswert, möglichen Lösungswerten vom Programm verwaltet, mögliche Lösungswerte von User gesetzt, Sperrzelle mit und ohne Sperrwert und farbliche Markierung durch den User) verwende, wird über diese die vermeintlich referenzierte Zelle im Str8ts-Feld (zweidimensionales int-Array) nicht verändert.

Derzeit verwende ich ein eindimensionales Array der Klasse ZELLPOS. Damit kann ich auf die Quelldaten zugreifen und sie auch ändern.


----------



## mrBrown (13. Aug 2017)

kodela hat gesagt.:


> Wenn ich das wüsste! Ich kann nur sagen, auch wenn ich an Stelle eines "normalen" Integerwertes eine eigene Klasse mit einem Integerwert für den Inhalt einer Zelle (bitcodiert mit Vorgabewert, Lösungswert, möglichen Lösungswerten vom Programm verwaltet, mögliche Lösungswerte von User gesetzt, Sperrzelle mit und ohne Sperrwert und farbliche Markierung durch den User) verwende, wird über diese die vermeintlich referenzierte Zelle im Str8ts-Feld (zweidimensionales int-Array) nicht verändert.


Dann hast du da irgendwas falsch gemacht - wenn Array und dein anderer Code das gleiche Objekt referenzierten, ist es das gleiche Objekt und ändert sich in beiden gleich.
Zeig mal Code dazu


----------



## kodela (13. Aug 2017)

mrBrown hat gesagt.:


> Dann hast du da irgendwas falsch gemacht - wenn Array und dein anderer Code das gleiche Objekt referenzierten, ist es das gleiche Objekt und ändert sich in beiden gleich.


Mag sein, dass ich etwas falsch mache, ich weiß aber nicht, was. Hier auszugsweise mein Code:

```
public class STR8TSAUSWERTUNG implements GlobaleVariablen {

    . . .
 
    private final int[][] strFeld = new int[9][9];
    private final STR8[] strList = new STR8[60];
    private final ZELLE[] zelle = new ZELLE[9]; 
 
    . . .
 
    public STR8TSAUSWERTUNG(Str8tsApp mFrame) {

        . . .
     
        for (int i = 0; i < 9; i++) {
                zelle[i] = new ZELLE();
            }
        }
    }
 
 
    // Mit "initAuswertung(aktStr)" werden alle Str8ts gesucht und
    // als STR8-Objekte in die Liste "strList" aufgenommen.
 
    // Mit "auswertenStr8t" werden die Str8ts in Abhängigkeit
    // ihrer Länge den speziellen Auswertemethoden übergeben.
    // zum Beispiel mit:
 
    geaendert += check2Str(strList[i]);
 
    . . .
 
    /**
     * Wertet Straßen der Länge Zwei aus.
     * @param str8t Infos füe eine 2er-Str8t
     * @return      Anzahl der vorgenommenen Änderungen
     */
    private int check2Str(STR8 str8t) {
 
        . . .
     
        wrt[0] = strFeld[str8t.ezPos.zl][str8t.ezPos.sp];
     
        // zum Testen auch mit:
        zelle[0].wert = strFeld[str8t.ezPos.zl][str8t.ezPos.sp];
     
        . . .
     
        // Auswertung für "strFeld" bedingt Änderung Str8ts-Feld
        // zuerst über die zu testende Klasseninstanz zelle:     

->      zelle[0].wert &= mK2[wrt[1]];

        // Der Wert in "strFeld" hat sich nicht verändert
     
        // Jetzt mit direkter Adressierung:
     
        strFeld[str8t.ezPos.zl][str8t.ezPos.sp] &= mK2[wrt[1]];
     
        // Die Änderung wird in "strFeld" übernommen.
     
        . . .
     
    }
 
    . . .
 
     /**
     * Klasse für die Definition einer Str8t durch die Positionsangabe
     * der jeweils ersten und letzten Zelle der Str8t und deren Länge
     */
    private class STR8 {
        ZPOS ezPos = null;
        ZPOS lzPos = null;
        int len = 0;
        boolean geloest = false;
        // Konstruktor
        public STR8() {
            this.ezPos = new ZPOS();
            this.lzPos = new ZPOS();
        }
    } 
 
    /**
     * Für Testzwecke eingefügte Klasse
     */
    private class ZELLE {
        int wert;
    }
}
```


----------



## mrBrown (13. Aug 2017)

Ich weiß nicht was du erreichen willst, aber jetzt hast du immer noch das `int[][]` und zusätzlich ein eindimensionales Zellen-Array?


----------



## kodela (13. Aug 2017)

mrBrown hat gesagt.:


> . . . hast du immer noch das int[][] und zusätzlich ein eindimensionales Zellen-Array?


Was Du mit dem "int[][]" meinst, ist das zweidimensionale Array (9 Zeilen und 9 Spalten) mit den auszuwertenden Daten für ein Str8ts.
Das (zusätzliche) eindimensionale Zellen-Array steht hier nur für den Test auf die Brauchbarkeit der von Dir angeregten "zusätzliche Klasse Feld" und ersetzt die in meinem ersten geposteten Code (private final int[] zellWert = new int[9] ) das eindimensionale Array "zellWert".
Während ich dies hier schreibe schwant mir, dass wir aneinander vorbei argumentiert haben. Ich hatte von Anfang an Zweifel wegen der "zusätzlichen Klasse Feld" und habe auch nachgefragt, was genau damit gemeint ist. Deine Antwort war: "Für eine Zelle". Das bezog ich auf einen Eintrag im int-Array "zellWert", mit dem genau ich ja das Problem habe. In diesem Array werden von den Zellen der gerade auszuwertenden Str8t die Werte gespeichert und auch verändert.
Wären in diesen int-Variablen nicht die Werte sondern Referenzen auf die Werte im zweidimensionalen Array "strFeld" gespeichert, würden sich die Auswirkungen der Änderung einfacher gestalten. Darauf zielte meine Frage.
Mittlerweile gehe ich davon aus, dass sich mein Gedanke nicht so wie zum Beispiel unter C/C++ realisieren lässt und ich habe eine andere Lösung gefunden. Wie im Beitrag #7 schon erwähnt, verwende ich dafür ein eindimensionales Array der Klasse ZELLPOS.
Ich danke Dir für Deine Bereitschaft, mir zu helfen.


----------



## mrBrown (13. Aug 2017)

Das wäre ziemlich einfach zu lösen gewesen mit einem `Zelle[][]` statt dem int.
Das wäre einerseits schöneres Design und andererseits etwa Äquivalent zu Pointer/Referenz in C/C++


----------



## Xyz1 (13. Aug 2017)

mrBrown hat gesagt.:


> etwa Äquivalent zu Pointer/Referenz in C/C++


Bla bla, jede Referenz ist doch äquivalent zu einem Pointer. Man hat hier nur einen anderen Begriff gewählt. Also die hellste Kerze auf dem Kuchen.... Ach, lassen wir das.


----------



## mrBrown (13. Aug 2017)

DerWissende hat gesagt.:


> Bla bla, jede Referenz ist doch äquivalent zu einem Pointer. Man hat hier nur einen anderen Begriff gewählt. Also die hellste Kerze auf dem Kuchen.... Ach, lassen wir das.


Was?

Um deinen Satz fortzuführen: ...bist du vermutlich nicht, zumindest hast du grad absolut keine Ahnung wovon du redest.


----------



## Blender3D (13. Aug 2017)

DerWissende hat gesagt.:


> Bla bla, jede Referenz ist doch äquivalent zu einem Pointer. Man hat hier nur einen anderen Begriff gewählt. Also die hellste Kerze auf dem Kuchen.... Ach, lassen wir das.


Zur Info Pointer und Referenz sind beides Zeiger.
Unterschied eine Referenz ist konstant kann nicht mehr geändert werden. Aber einem Pointer kann man ändern.
Siehe Pointer Arithmetik in C oder C++
Also ist ein Pointer nicht gleich einer Referenz.


----------



## Xyz1 (13. Aug 2017)

Blender3D hat gesagt.:


> Siehe Pointer Arithmetik in C oder C++


Wer sagt nochmal, dass sich Pointer durch Pointer Arithmetik definiert?


----------



## Blender3D (13. Aug 2017)

DerWissende hat gesagt.:


> Wer sagt nochmal, dass sich Pointer durch Pointer Arithmetik definiert?


In C gibt es Pointer und Referenzen. Das ist nicht das Gleiche. Referenzen in C entsprechen Referenzen in Java.


----------



## mrBrown (14. Aug 2017)

Blender3D hat gesagt.:


> In C gibt es Pointer und Referenzen. Das ist nicht das Gleiche. Referenzen in C entsprechen Referenzen in Java.


Ne, Referenzen in Java sind nicht konstant


----------



## Blender3D (14. Aug 2017)

mrBrown hat gesagt.:


> Ne, Referenzen in Java sind nicht konstant


Object ref = new Object();
ref =  die Adresse des Speichers des Objekt.
Lässt sich nur mehr auf null, oder mittels new auf einen neuen Speicherbereich setzen also konstant.
in C:
char* cp = (char*) malloc(sizeof(char) * 4);
strcpy( cp, "ABC" );
cp zeigt auf A
cp++;
cp zeigt auf B
nicht konstant.


----------



## mrBrown (14. Aug 2017)

Blender3D hat gesagt.:


> Object ref = new Object();
> ref =  die Adresse des Speichers des Objekt.
> Lässt sich nur mehr auf null, oder mittels new auf einen neuen Speicherbereich setzen also konstant.
> in C:
> ...


`ref=„Ananas“;`
Und schwupps zeigt ref auf ein anderes Bereich.

Aber vergleichen lässt sich Java da schwer mit C/C++, wichtig ist nur, dass für deinen Fall Objekte das richtige wären, ganz unabhängig von Java-Reference, C++-Reference und Pointer


----------



## kodela (14. Aug 2017)

mrBrown hat gesagt.:


> . . . wichtig ist nur, dass für deinen Fall Objekte das richtige wären . . .


Danke @mrBrown, ich sehe das mittlerweile auch so und werde daher prüfen, ob ich an der derzeitigen Struktur etwas verändere. Eine Veränderung hätte weitreichende Auswirkungen, denn die Klasse, um die es mir hier ging, spielt im Grunde nur eine sehr untergeordnete Rolle. Sie wird nach der Neueingabe einer Str8ts-Aufgabe einmal aufgerufen, bekommt die Aufgabe als eindimensionales int-Array mit 81 Werten vorgesetzt, konvertiert sie wegen der besseren Auswertungsmöglichkeiten in ein zweidimensionales Array und soll die Lösung per strategischen Regeln finden. Damit eine Umstellung Sinn macht, müsste ich also auch die weit umfangreichere Aufrufklasse und eine Vielzahl weiterer Klassen an die geänderte Struktur anpassen.


----------

