当前位置: 首页 > 面试题库 >

Java集合协方差问题

公冶同
2023-03-14
问题内容

可以说我们有一个包含此类的程序:

public interface AbstractItem {
}
public SharpItem implements AbstractItem {
}
public BluntItem implements AbstractItem {
}

public interface AbstractToolbox {
    //well the problem starts here...
    public List<AbstractItem> getItems();
}
public ExpensiveToolbox implements AbstractToolbox {
    private List<SharpItem> items = new ArrayList()<SharpItems>;
    public List<SharpItem> getItems() { return this.items; }
}
public CheapTooblox implements AbstractToolbox {
    private List<BluntItem> items = new ArrayList()<BluntItem>;
    public List<BluntItem> getItems() { return this.items; }
}

容易吧?好吧,可以说我们现在想要制作这样的方法(在某个随机类中):

public void doImportantStuff(AbstractToolbox toolbox) {
//important stuff!
//this obviously won't work
    List<AbstractToolbox> items = toolbox.getItems();
//do some stuffwith all items
}

现在的问题是,在Java的泛型集合不是协变的(希望这是我要找的术语),我不能分配ArrayList<ExpensiveToolbox>给一个List<AbstractToolbox>。我在这里看到的唯一解决方案是复制代码并为每种类型做一个版本,但这显然很糟糕(如果我们有更多的类用不同的列表实现AbstractToolbox会怎样?)。哦,显然,第二种解决方法是删除泛型并创建一个普通的List,但这是一个好习惯吗?

是否有解决此类问题的设计模式/实践?

@Edit:好的,所以我可能不够精确。我希望所有扩展AbstractToolbox的类都具有某些扩展AbstractItem的类的列表,然后我想要一个方法,该方法将AbstractToolbox作为参数并对其列表中的项目进行某些操作(使用将在AbstractItem,因此每个可能的列表中的所有项目实际上都具有它们)。


问题答案:

您可能需要看一下对通配符使用通配符类型。快速链接如下:
什么是PECS(生产者扩展了超级消费者)?

快速解答:将类型更改为 List<? extends AbstractItem>

你为什么不能分配这个?

想象一下这里的代码

List<AbstractItem> foo = new ArrayList<SharpItem>();
foo.add(new BluntItem());

静态打字说这应该工作…但是你不能这样做!它将违反ArrayList的类型。这就是为什么不允许这样做。如果您将其更改为

List<? extends AbstractItem> foo = new ArrayList<SharpItem>();

然后,您可以进行分配,但不要在列表中添加任何内容。但是,您仍然可以从列表中检索元素作为AbstractItems。

仅使用列表(裸类型)是否是一个好的解决方案?

不,绝对不是:-p



 类似资料:
  • 问题内容: 请显示一个有关Java中协方差和逆方差的好例子。 问题答案: 协方差: Sub#getSomething是协变的,因为它返回Super#getSomething的返回类型的子类(但完全填充了Super.getSomething()的协定) 逆差 Sub#doSomething是互变的,因为它采用了Super#doSomething的参数的超类的参数(但是,再次填充了Super#doSo

  • sdiff key1 key2...keyN 返回所有给定key的差集 sdiffstore dstkey key1...keyN 同sdiff,并同时保存差集到dstkey下

  • 问题内容: 谁能解释我,编程语言理论中协变和逆变的概念吗? 问题答案: 协方差 非常简单,最好从某些收集类的角度来考虑。我们可以 参数化 的一些类型参数类。也就是说,我们的列表包含some 类型的元素。如果,列表将是协变的 S是Tiff列表的子类型List [S]是List [T]的子类型 (在这里,我使用数学定义 iff 表示 当且仅当 。) 也就是说,a 是一个 。如果有一些例程接受a 作为参

  • 你能解释一下第一行最后一个false输出,为什么它不是真的吗?

  • 我正在学习Scala中的函数式编程原理,在学习子类型和泛型时,我对协方差有一个困惑: 给定:或是的子类型 编辑: 下面是的定义:

  • 2.8.1. 基本收敛 尽管是协方差矩阵的无偏估计, 最大似然估计不是协方差矩阵的特征值的一个很好的估计, 所以从反演得到的精度矩阵是不准确的。 有时,甚至出现数学原因,经验协方差矩阵不能反转。 为了避免这样的反演问题,引入了经验协方差矩阵的一种变换方式:shrinkage 。 在 scikit-learn 中,该变换(具有用户定义的收缩系数) 可以直接应用于使用 shrunk_covarianc