泛型问题java

Wil*_*oat 2 java generics inheritance

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);
Run Code Online (Sandbox Code Playgroud)

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>>)
Run Code Online (Sandbox Code Playgroud)

你能解释一下我为什么这样以及如何解决它?

Gio*_*tta 6

你需要声明result它是什么,即a GetResponse<AdWordsKeywordIdentifier>.

编辑:

看看你的变化,我发现了一个大问题.您正尝试setMetrics使用两个不同类型的列表调用该方法.你根本做不到.由于GetResponse是参数T化的,因此列表中元素的类型必须是精确的T,即,AdWordsKeywordIdentifier 或者 BingKeywordIdentifier,它们不能同时存在.编译器抱怨因为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;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在只适用于原始代码段:

GetResponse result = new GetResponse();
List<KeywordMetrics<AdWordsKeywordIdentifier>> stats = new ArrayList<>();
List<KeywordMetrics<BingKeywordIdentifier>> stats2 = new ArrayList<>();    result.setMetrics(stats);
result.setMetrics(stats2);
Run Code Online (Sandbox Code Playgroud)

这一切都取决于你想要达到的目标.上面的代码仍然是类型安全的.既然你说你希望你的代码"通用",你必须放弃在编译时知道列表的确切类型(它现在是一个列表? extends KeywordMetrics<? extends KeywordIdentifier>).

请注意,进行此编译需要双通配符.A List<KeywordMetrics<BingKeywordIdentifier>> 是a List<? extends KeywordMetrics<? extends KeywordIdentifier>>不是a List<KeywordMetrics<? extends KeywordIdentifier>>.


小智 5

您没有使用正确的类型参数化声明变量结果.因此,编译器无法保证使用此列表调用setMetrics方法应该有效.

把它改成

GetResponse<AdWordsKeywordIdentifier> result = ....
Run Code Online (Sandbox Code Playgroud)

应该解决它.