泛型问题Java - java

public class GetResponse <T extends KeywordIdentifier>{

    private List<KeywordMetrics<T>> metrics = null;


public List<KeywordMetrics<T>> getMetrics(){
        return this.metrics;
    }

    public void setMetrics(List<KeywordMetrics<T>> metrics){
        this.metrics = metrics;
    }
}


public class AdWordsKeywordIdentifier extends KeywordIdentifier {
//body
}
public class BingKeywordIdentifierextends KeywordIdentifier {
//body
}


GetResponse<? extends KeywordIdentifier> result= new GetResponse<AdWordsKeywordIdentifier>();
List<KeywordMetrics<AdWordsKeywordIdentifier>> stats = getGoogleStats();
List<KeywordMetrics<BingKeywordIdentifier>> stats2 = getBingStats();
result.setMetrics(stats);
result.setMetrics(stats2);

result.setMetrics(stats)方法产生编译错误。

ERROR (The method setMetrics(List<KeywordMetrics<capture#2-of ?extends KeywordIdentifier>>) in the type GetResponse<capture#2-of ?extends KeywordIdentifier> is not applicable for the arguments(List<KeywordMetrics<AdWordsKeywordIdentifier>>)

您能否解释一下为什么会这样,我该如何解决?

参考方案

您需要声明result的名称,即GetResponse<AdWordsKeywordIdentifier>

编辑:

查看您的更改,我看到了一个大问题。您正在尝试使用两种不同类型的两个列表调用setMetrics方法。您根本无法做到这一点。由于GetResponse是用T参数化的,因此列表中元素的类型必须完全是T,即AdWordsKeywordIdentifierBingKeywordIdentifier,不能两者都使用。编译器在抱怨,因为GetResponse具有类型参数? extends KeywordIdentifier,并且无法推断出实际的类型参数是什么,因此它不能静态地确保setMetrics方法调用的类型安全,即,您永远不会能够调用它。

虽然并没有全部丢失。您必须做出选择:要么使通用类保持不变,然后始终强制强类型化,要么可以使该类不是通用类,并按如下所示修改metrics字段:

class GetResponse {

  private List<? extends KeywordMetrics<? extends KeywordIdentifier>> metrics = null;

  public List<? extends KeywordMetrics<? extends KeywordIdentifier>> getMetrics() {
    return this.metrics;
  }

  public void setMetrics(List<? extends KeywordMetrics<? extends KeywordIdentifier>> metrics) {
    this.metrics = metrics;
  }
}

现在仅适用于您的原始代码段:

GetResponse result = new GetResponse();
List<KeywordMetrics<AdWordsKeywordIdentifier>> stats = new ArrayList<>();
List<KeywordMetrics<BingKeywordIdentifier>> stats2 = new ArrayList<>();    result.setMetrics(stats);
result.setMetrics(stats2);

这完全取决于您要实现的目标。上面的代码仍然是类型安全的。因为您说过要“通用”代码,所以您必须放弃在编译时知道列表的确切类型(现在是? extends KeywordMetrics<? extends KeywordIdentifier>的列表)。

请注意,进行此编译需要使用双通配符。 List<KeywordMetrics<BingKeywordIdentifier>>List<? extends KeywordMetrics<? extends KeywordIdentifier>>,但不是List<KeywordMetrics<? extends KeywordIdentifier>>

无法从ArrayList <String>转换为List <Comparable> - java

当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…

用glassfish服务器进行struts2会话维护 - java

在我的应用程序中,有5分钟的会话超时。<session-config> <session-properties> <property name="timeoutSeconds" value="300"></property> </session-properties…

Java中的“ <<”运算符 - java

最喜欢的语句来自Java的Character类:(1 << Character.PARAGRAPH_SEPARATOR)) >> type PARAGRAPH_SEPARATOR是字节,type是整数。这句话中的操作员,他们做什么?如何以及在哪里可以使用这些运算符?这是oracles java.lang.Character文档。该类中…

合并List <T>和List <Optional <T >> - java

鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…

展平地图中的列表列表 - java

我有订单流(来源是订单列表)。每个订单都有一个客户和一个OrderLine列表。我要实现的目标是在一张简单的列表中以客户为关键的地图,并将属于该客户的所有订单行作为值。现在,通过执行以下操作,我现在管理的内容返回了Map<Customer>, List<Set<OrderLine>>>:orders .collect…