Este problema tiene dos causas típicas:
Campos estáticos
Si los objetos en su lista almacenan datos en campos estáticos, cada objeto en su lista parecerá ser el mismo porque tienen los mismos valores. Considere la clase a continuación:
public class Foo {
private static int value;
public Foo(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
En ese ejemplo, solo hay uno int value
que se comparte entre todas las instancias de Foo
porque está declarado static
. (Consulte el tutorial "Comprensión de los miembros de la clase" ).
Si agrega varios Foo
objetos a una lista con el código siguiente, cada instancia volverá 3
de una llamada a getValue()
:
for (int i = 0; i < 4; i++) {
list.add(new Foo(i));
}
La solución es simple: no use las static
palabras clave para los campos de su clase a menos que realmente desee que los valores se compartan entre cada instancia de esa clase.
Agregar el mismo objeto
Si agrega una variable temporal a una lista, debe crear una nueva instancia del objeto que está agregando, cada vez que realice un bucle. Considere el siguiente fragmento de código erróneo:
List<Foo> list = new ArrayList<Foo>();
Foo tmp = new Foo();
for (int i = 0; i < 3; i++) {
tmp.setValue(i);
list.add(tmp);
}
Aquí, el tmp
objeto se construyó fuera del bucle. Como resultado, la misma instancia de objeto se agrega a la lista tres veces. La instancia mantendrá el valor 2
, porque ese fue el valor pasado durante la última llamada a setValue()
.
Para solucionar esto, simplemente mueva la construcción del objeto dentro del ciclo:
List<Foo> list = new ArrayList<Foo>();
for (int i = 0; i < 3; i++) {
Foo tmp = new Foo();
tmp.setValue(i);
list.add(tmp);
}
tmp
) se agrega a la lista tres veces. Y ese objeto tiene un valor de dos, debido a la llamada atmp.setValue(2)
en la iteración final del ciclo.you must create a new instance each time you loop
de la secciónAdding the same object
: tenga en cuenta que la instancia a la que se hace referencia se refiere al objeto que está agregando, NO al objeto al que lo está agregando.Su problema es con el tipo
static
que requiere una nueva inicialización cada vez que se itera un bucle. Si está en un bucle, es mejor mantener la inicialización concreta dentro del bucle.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); }
En vez de:
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 }
Aquí
tag
hay una variableSomeStaticClass
para verificar la validez del fragmento anterior; puede tener alguna otra implementación basada en su caso de uso.fuente
static
"? ¿Qué sería una clase no estática para ti?public class SomeClass{/*some code*/}
y estática:public static class SomeStaticClass{/*some code*/}
. Espero que ahora esté más claro.Tuve el mismo problema con la instancia del calendario.
Codigo erroneo:
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); }
Tienes que crear un objeto NUEVO del calendario, que se puede hacer con
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); }
fuente
Cada vez que agregue un objeto a una ArrayList, asegúrese de agregar un nuevo objeto y no un objeto ya utilizado. Lo que está sucediendo es que cuando agrega la misma 1 copia de objeto, ese mismo objeto se agrega a diferentes posiciones en una ArrayList. Y cuando cambia uno, porque se agrega la misma copia una y otra vez, todas las copias se ven afectadas. Por ejemplo, digamos que tiene una ArrayList como esta:
ArrayList<Card> list = new ArrayList<Card>(); Card c = new Card();
Ahora, si agrega esta Tarjeta c a la lista, se agregará sin problemas. Se guardará en la ubicación 0. Pero, cuando guarde la misma Tarjeta c en la lista, se guardará en la ubicación 1. Así que recuerde que agregó el mismo 1 objeto a dos ubicaciones diferentes en una lista. Ahora bien, si realiza un cambio en el objeto Tarjeta c, los objetos de una lista en la ubicación 0 y 1 también reflejarán ese cambio, porque son el mismo objeto.
Una solución sería hacer un constructor en la clase Card, que acepte otro objeto Card. Luego, en ese constructor, puede establecer las propiedades de esta manera:
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 }
Y digamos que tiene la misma copia 1 de Card, por lo que al momento de agregar un nuevo objeto, puede hacer esto:
list.add(new Card(nameOfTheCardObjectThatYouWantADifferentCopyOf));
fuente
También puede ser consecuencia de utilizar la misma referencia en lugar de utilizar una nueva.
List<Foo> list = new ArrayList<Foo>(); setdata(); ...... public void setdata(int i) { Foo temp = new Foo(); tmp.setValue(i); list.add(tmp); }
En vez de:
List<Foo> list = new ArrayList<Foo>(); Foo temp = new Foo(); setdata(); ...... public void setdata(int i) { tmp.setValue(i); list.add(tmp); }
fuente