简体   繁体   English

具有接口上限的设置器,但没有通配符的获取器

[英]Setter with upper bound of Interface, but getter without wildcard

As recommended by Sonar rule RSPEC-1452 ,根据声纳规则RSPEC-1452 的建议,

Generic wildcard types should not be used in return types不应在返回类型中使用通用通配符类型

How can I define setter method of a property that accepts a List<? extends Item>如何定义接受List<? extends Item> List<? extends Item> , but getter method that returns List<Item> ? List<? extends Item> ,但返回List<Item>的 getter 方法?

Consider the below contract of Cart interface:考虑以下Cart接口的合约:

interface Cart {
    public List<Item> getItems();
}

interface Item {
    public int getCost();
}

Clients of this contract do not need to know about any known implementations of Cart or Item interfaces, eg此合约的客户不需要知道任何已知的CartItem接口的实现,例如

void getValue(Cart cart) {
    int sum = cart.getItems().stream().mapToInt(Item::getCost).sum();
}

However, the library that implements the Cart interface obviously has to deal with concrete classes.然而,实现Cart接口的库显然必须处理具体的类。 Assume it (or its Builder ) also has to expose a setItems method so that another internal class can set the entire list of items.假设它(或其Builder )还必须公开一个setItems方法,以便另一个内部 class 可以设置整个项目列表。 Upper bound of Interface allows to pass a List<DefaultItem> to setItems method. Interface 的上限允许将List<DefaultItem>传递给setItems方法。

static class DefaultCart implements Cart {

    private List<Item> items;

    public void setItems(List<? extends Item> items) {
        this.items = new ArrayList<Item>(items);
    }

    @Override
    public List<Item> getItems() {
        return items;
    }
}

I am not happy with the above setItems method as it creates another copy of the list.我对上面的setItems方法不满意,因为它创建了列表的另一个副本。 What is a better way of dealing with this?有什么更好的方法来处理这个问题?

How can I define setter method of a property that accepts a List<? extends Item>如何定义接受List<? extends Item> List<? extends Item> , but getter method that returns List<Item> ? List<? extends Item> ,但返回List<Item>的 getter 方法?

You can't, because List<? extends Item>你不能,因为List<? extends Item> List<? extends Item> is not a subclass of List<Item> , ie they are not assignment compatible with each other. List<? extends Item>不是List<Item>的子类,即它们之间的赋值不兼容。

For explanation, see: Is List<Dog> a subclass of List<Animal>解释见: List<Dog>List<Animal>的子类吗

What you can do, is to make your class generic, so you don't use wildcard:你可以做的是让你的 class 通用,所以你不使用通配符:

static class DefaultCart<E extends Item> implements Cart {

    private List<E> items;

    public void setItems(List<E> items) {
        this.items = items;
    }

    @Override
    public List<E> getItems() {
        return items;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM