Dieses Problem hat zwei typische Ursachen:
Statische Felder, die von den Objekten verwendet werden, die Sie in der Liste gespeichert haben
Versehentlich dasselbe Objekt zur Liste hinzufügen
Statische Felder
Wenn die Objekte in Ihrer Liste Daten in statischen Feldern speichern, scheint jedes Objekt in Ihrer Liste dasselbe zu sein, da sie dieselben Werte enthalten. Betrachten Sie die folgende Klasse:
public class Foo {
private static int value;
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
In diesem Beispiel gibt es nur eine, int value
die von allen Instanzen gemeinsam genutzt wird, Foo
weil sie deklariert ist static
. (Siehe Tutorial "Grundlegendes zu Klassenmitgliedern" .)
Wenn Sie Foo
einer Liste mit dem folgenden Code mehrere Objekte hinzufügen , kehrt jede Instanz 3
von einem Aufruf an Folgendes zurück getValue()
:
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
Die Lösung ist einfach: Verwenden Sie die static
Schlüsselwörter nicht für Felder in Ihrer Klasse, es sei denn, Sie möchten tatsächlich, dass die Werte von jeder Instanz dieser Klasse gemeinsam genutzt werden.
Hinzufügen des gleichen Objekts
Wenn Sie einer Liste eine temporäre Variable hinzufügen, müssen Sie bei jeder Schleife eine neue Instanz des hinzuzufügenden Objekts erstellen. Betrachten Sie das folgende fehlerhafte Code-Snippet:
List<Foo> list = new ArrayList<Foo>();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Hier wurde das tmp
Objekt außerhalb der Schleife konstruiert. Infolgedessen wird dieselbe Objektinstanz dreimal zur Liste hinzugefügt. Die Instanz enthält den Wert 2
, da dies der Wert war, der beim letzten Aufruf von übergeben wurde setValue()
.
Um dies zu beheben, verschieben Sie einfach die Objektkonstruktion innerhalb der Schleife:
List<Foo> list = new ArrayList<Foo>();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo();
tmp.setValue(i);
list.add(tmp);
}
tmp
) dreimal zur Liste hinzugefügt wird. Und dieses Objekt hat aufgrund des Aufrufstmp.setValue(2)
in der letzten Iteration der Schleife den Wert zwei .you must create a new instance each time you loop
im AbschnittAdding the same object
: Bitte beachten Sie, dass die Instanz, auf die Bezug genommen wird, das Objekt betrifft, das Sie hinzufügen, NICHT das Objekt, zu dem Sie es hinzufügen.Ihr Problem liegt in dem Typ,
static
der bei jeder Iteration einer Schleife eine neue Initialisierung erfordert. Wenn Sie sich in einer Schleife befinden, ist es besser, die konkrete Initialisierung in der Schleife zu belassen.List<Object> objects = new ArrayList<>(); for (int i = 0; i < length_you_want; i++) { SomeStaticClass myStaticObject = new SomeStaticClass(); myStaticObject.tag = i; // Do stuff with myStaticObject objects.add(myStaticClass); }
Anstatt von:
List<Object> objects = new ArrayList<>(); SomeStaticClass myStaticObject = new SomeStaticClass(); for (int i = 0; i < length; i++) { myStaticObject.tag = i; // Do stuff with myStaticObject objects.add(myStaticClass); // This will duplicate the last item "length" times }
Hier
tag
ist eine VariableSomeStaticClass
, um die Gültigkeit des obigen Snippets zu überprüfen. Sie können je nach Anwendungsfall eine andere Implementierung durchführen.quelle
static
"? Was wäre für Sie eine nicht statische Klasse?public class SomeClass{/*some code*/}
& statisch :public static class SomeStaticClass{/*some code*/}
. Ich hoffe es ist jetzt klarer.Hatte das gleiche Problem mit der Kalenderinstanz.
Falscher Code:
Calendar myCalendar = Calendar.getInstance(); for (int days = 0; days < daysPerWeek; days++) { myCalendar.add(Calendar.DAY_OF_YEAR, 1); // In the next line lies the error Calendar newCal = myCalendar; calendarList.add(newCal); }
Sie müssen ein NEUES Objekt des Kalenders erstellen, was möglich ist
calendar.clone()
.Calendar myCalendar = Calendar.getInstance(); for (int days = 0; days < daysPerWeek; days++) { myCalendar.add(Calendar.DAY_OF_YEAR, 1); // RIGHT WAY Calendar newCal = (Calendar) myCalendar.clone(); calendarList.add(newCal); }
quelle
Stellen Sie bei jedem Hinzufügen eines Objekts zu einer ArrayList sicher, dass Sie ein neues Objekt und ein noch nicht verwendetes Objekt hinzufügen. Wenn Sie dieselbe 1 Kopie des Objekts hinzufügen, wird dasselbe Objekt an verschiedenen Positionen in einer ArrayList hinzugefügt. Und wenn Sie eine Änderung vornehmen, werden alle Kopien betroffen, da immer wieder dieselbe Kopie hinzugefügt wird. Angenommen, Sie haben eine ArrayList wie folgt:
ArrayList<Card> list = new ArrayList<Card>(); Card c = new Card();
Wenn Sie nun diese Karte c zur Liste hinzufügen, wird sie problemlos hinzugefügt. Es wird an Position 0 gespeichert. Wenn Sie jedoch dieselbe Karte c in der Liste speichern, wird sie an Position 1 gespeichert. Denken Sie also daran, dass Sie dasselbe 1 Objekt an zwei verschiedenen Positionen in einer Liste hinzugefügt haben. Wenn Sie nun das Kartenobjekt c ändern, spiegeln die Objekte in einer Liste an den Positionen 0 und 1 diese Änderung ebenfalls wider, da sie dasselbe Objekt sind.
Eine Lösung wäre, einen Konstruktor in der Kartenklasse zu erstellen, der ein anderes Kartenobjekt akzeptiert. Dann können Sie in diesem Konstruktor die Eigenschaften wie folgt festlegen:
public Card(Card c){ this.property1 = c.getProperty1(); this.property2 = c.getProperty2(); ... //add all the properties that you have in this class Card this way }
Angenommen, Sie haben dieselbe 1 Kopie der Karte. Wenn Sie also ein neues Objekt hinzufügen, können Sie Folgendes tun:
list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
quelle
Dies kann auch dazu führen, dass dieselbe Referenz anstelle einer neuen verwendet wird.
List<Foo> list = new ArrayList<Foo>(); setdata(); ...... public void setdata(int i) { Foo temp = new Foo(); tmp.setValue(i); list.add(tmp); }
Anstatt von:
List<Foo> list = new ArrayList<Foo>(); Foo temp = new Foo(); setdata(); ...... public void setdata(int i) { tmp.setValue(i); list.add(tmp); }
quelle