首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有List字段的Spring BeanUtils复制属性

具有List字段的Spring BeanUtils复制属性
EN

Stack Overflow用户
提问于 2017-02-26 22:17:43
回答 2查看 22.5K关注 0票数 7

我有Foo和Item类,如下所示。

代码语言:javascript
复制
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 + '\'' + '}';
    }
}

当我使用spring BeanUtils复制Foo类时,列表字段的引用没有改变。

代码语言:javascript
复制
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());
    }
}

SimpleCopyMain类的输出如下:

代码语言:javascript
复制
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'}]

但是,当我为list字段创建一个新实例并逐个复制引用时,我得到了预期的行为。

代码语言:javascript
复制
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());
    }
}

下面是输出:

代码语言:javascript
复制
fooSnapShot id field value is not changing as expected : 1
fooSnapShot items value is is not changing : [Item{bar='item1'}, Item{bar='item2'}]

还有我的pom:

代码语言:javascript
复制
<?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>

为什么spring beanutils不克隆列表字段?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-26 22:41:04

根据Spring的实现,BeanUtil通过Getter和Setter复制数据。如果你有像Integer这样的原语,这是可以的,但是对于你的List字段,你可以在Setter中传递引用。

如果你想让它工作,你需要改变你的setter为:

代码语言:javascript
复制
public void setItems(List<Item> items) {
        this.items = new ArrayList<>(items);
}

这也会做浅拷贝,但是你不会有列表引用。

票数 7
EN

Stack Overflow用户

发布于 2017-02-26 22:32:55

如果查看一下spring的BeanUtils.copyProperties,就会发现所有这些操作都是执行属性的浅层复制,这意味着只有具有原始值的属性才会被克隆,所有其他属性都将通过引用进行复制。在幕后,Spring使用PropertyDescriptor并调用源属性上的getter和目标属性中的setter。

因此,当您调用BeanUtils.copyProperties(foo, fooSnapShot);时,foo和fooSnapShot共享对items列表的相同引用,这就是为什么可以通过foo或fooSnapshot实例更改该列表的原因,然而,在第二种情况下,您为fooSnapShot提供了一个对不同列表fooSnapShot.setItems(new ArrayList<Item>(foo.getItems().size()));的引用,这就是您获得预期结果的原因。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42469618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档