【问题标题】:Merge two collections of the same type (which are capture of template)? [duplicate]合并两个相同类型的集合(它们是模板的捕获)? [复制]
【发布时间】:2022-01-04 17:21:14
【问题描述】:

假设我有以下两个类:

public class SomethingElse<A, B> {

    public List<? extends Something<A, B>> getOneList() {
        //doesn't matter
    }

    public List<? extends Something<A, B>> getAnotherList() {
        //doesn't matter
    }

}

public class Something<A, B> {
    //doesn't matter
}

我想合并从getOneList()getAnotherList() 得到的结果:

SomethingElse<String, Integer> somethingElse = new SomethingElse<>();
List<? extends Something<String, Integer>> oneList = somethingElse.getOneList();
List<? extends Something<String, Integer>> anotherList = somethingElse.getAnotherList();
anotherList.forEach(e -> oneList.add(e)); //<-- DOESN'T COMPILE

但是,编译器抱怨在上面的 .add() 方法中,它期望 capture of ? extends Something&lt;String, Integer&gt; 但我提供...好吧,capture of ? extends Something&lt;String, Integer&gt;

我觉得这与类型擦除有关,但我不知道为什么,甚至编译器本身也无法产生明确的消息,因为它告诉我我提供类型 X,但它期待类型 X。

谁能从技术上解释为什么编译器不喜欢这个?我可能会在同一个列表中做哪些错误的混合?

【问题讨论】:

  • tl;dr: anotherList 是生产者,oneList 是消费者。
  • @Turing85 非常感谢,重复的问题完美地回答了我的问题(但它没有弹出,因为我从未搜索过 PECS 术语 :)
  • PECS:生产者扩展,消费者超级。

标签: java generics


【解决方案1】:

你真的要继承这两个类,这样你就需要扩展了吗?你可以这样做,没有扩展。我建议您阅读 this,因为使用 extends 与 super 决定您是否可以从列表中添加或删除项目。

SomethingElse<String, Integer> somethingElse =
        new SomethingElse<>();
List<Something<String, Integer>> oneList =
        somethingElse.getOneList();
List<Something<String, Integer>> anotherList =
        somethingElse.getAnotherList();
    
anotherList.addAll(oneList);



class SomethingElse<A, B> {
    
    public List<Something<A, B>> getOneList() {
        return null;
    }
    
    public List<Something<A, B>> getAnotherList() {
        return null;
    }
    
}

class Something<A, B> {
    // doesn't matter
}

【讨论】:

  • 我无法修改 SomethingElse 类。虽然,我尝试删除 super 和 extends,但即使我需要未经检查的演员表,它也能正常工作。有什么办法可以避免吗?
  • 不幸的是,这是通配符以及泛型的逆变和具体化性质的问题。有关更多信息,您可能想查看Covariance vs Contravariance 上的这篇文章。它还讨论了获取/放置原则,即 PEC。它可能会就如何处理您的具体情况提供一些想法。
猜你喜欢
  • 1970-01-01
  • 2022-08-12
  • 2013-07-10
  • 2023-03-29
  • 2015-07-08
  • 2018-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多