Frühjahr BeanUtils Eigenschaften kopieren mit einem Bereich der Liste
Ich hava " Foo " und " Element-Klasse als unten.
import java.util.ArrayList;
import java.util.List;
public class Foo {
private Long id;
private List<Item> items;
public Foo(Long id) {
this.id = id;
this.items = new ArrayList<Item>();
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
public class Item {
private String bar;
public Item(String bar) {
this.bar = bar;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
@Override
public String toString() {
return "Item{" + "bar='" + bar + '\'' + '}';
}
}
Wenn ich kopieren die Klasse " Foo " mit spring BeanUtils die Referenz für die Liste das Feld ist nicht zu ändern.
import org.springframework.beans.BeanUtils;
public class SimpleCopyMain {
public static void main(String[] args) {
Foo foo = new Foo(1L);
foo.getItems().add(new Item("item1"));
foo.getItems().add(new Item("item2"));
Foo fooSnapShot = new Foo(100L);
BeanUtils.copyProperties(foo,fooSnapShot);
foo.setId(999L);
System.out.println("fooSnapShot id field value is not changing as expected : " + fooSnapShot.getId());
foo.getItems().add(new Item("item3"));
System.out.println("fooSnapShot items value is changing unexpectedly : " + fooSnapShot.getItems());
}
}
Die Ausgabe für SimpleCopyMain Klasse ist unten :
fooSnapShot id field value is not changing as expected : 1
fooSnapShot items value is changing unexpectedly : [Item{bar='item1'}, Item{bar='item2'}, Item{bar='item3'}]
Allerdings, wenn ich eine neue Instanz erstellen, für die Liste ein Feld und kopieren Sie die Referenzen ein, indem ein, bekomme ich das Verhalten, wie ich es erwartet habe.
import java.util.ArrayList;
import org.springframework.beans.BeanUtils;
public class CopyMain {
public static void main(String[] args) {
Foo foo = new Foo(1L);
foo.getItems().add(new Item("item1"));
foo.getItems().add(new Item("item2"));
Foo fooSnapShot = new Foo(100L);
BeanUtils.copyProperties(foo, fooSnapShot);
fooSnapShot.setItems(new ArrayList<Item>(foo.getItems().size()));
for(int i = 0; i < foo.getItems().size(); i++){
Item anItem = new Item("");
BeanUtils.copyProperties(foo.getItems().get(i), anItem);
fooSnapShot.getItems().add(anItem);
}
foo.setId(999L);
System.out.println("fooSnapShot id field value is not changing as expected : " + fooSnapShot.getId());
foo.getItems().add(new Item("item3"));
System.out.println("fooSnapShot items value is is not changing : " + fooSnapShot.getItems());
}
}
Hier ist die Ausgabe :
fooSnapShot id field value is not changing as expected : 1
fooSnapShot items value is is not changing : [Item{bar='item1'}, Item{bar='item2'}]
Und mein pom :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.question</groupId>
<artifactId>beanutils</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.3.RELEASE</version>
</dependency>
</dependencies>
</project>
Warum ist der Frühling beanutils nicht Klonen, eine Liste Feld ?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Laut BeanUtil copyProperities Methode der Umsetzung, der Frühling ist kopieren Sie Ihre Daten über Getter und Setter. Wenn Sie primitive, wie Integer, ist es ok, aber für dein Listenfeld, übergeben Sie die Referenz in Setter.
Wenn Sie möchten, es zu arbeiten, müssen Sie ändern Sie Ihre setter zu:
Wird dies tun, auch flache Kopie, aber Sie nicht Liste verweisen.
Wenn man sich die spring BeanUtils.copyProperties können Sie sehen, dass alle tun, ist die Durchführung eine seichte Kopie der Eigenschaften, was bedeutet, dass nur properties mit primitiven Werten geklont wird, alle anderen Eigenschaften werden kopiert-by-reference. Hinter den kulissen ist der Frühling mit PropertyDescriptor abgeleitet sind und dem Aufruf der getter auf der source-Eigenschaft und Aufruf der setter in der target-Eigenschaft.
Also, wenn Sie rufen
BeanUtils.copyProperties(foo, fooSnapShot);
im moment foo und fooSnapShot Anteil die gleiche Referenz der Elemente Liste, und das ist der Grund, warum die Liste kann geändert werden, durch die foo oder fooSnapshot Fällen jedoch, in Ihrem zweiten Fall geben Sie fooSnapShot einen Verweis auf eine andere ListefooSnapShot.setItems(new ArrayList<Item>(foo.getItems().size()));
und deshalb bekommen Sie Ihre erwarteten Ergebnisse.