java - 在这种情况下如何避免泛型?

标签 java generics

class Attribute<T>{
   private T attr;
   public Attribute(T attr){
      this.attr = attr;
   } 
}

Class Matrix<T>{
   private String name;
   List<Attribute<T>> list;

   public Matrix(String name, T t){
     this.name = name;
     list = new ArrayList<>();
     list.add(new Attribute<T>(t)); 
  }
}

 interface Extractor<T> {
    public List<Matrix<T>> extract();
}

InfoExtractor implements Extractor<String>{

    public List<Matrix<String>> extract(){ 
       List<Matrix<String>> matrixList = new ArrayList<>();

        // The problem is here!!!!
        matrixList.add(new Matrix<String>("abc")); 
    }
 }

 Document<T>{
      Map<String, List<Matrix<T>>> matrixMap;

        public void process(){
        ...
         Extractor<T> extractor = (Extractor<T>) new StringExtractor(sent);
        List<Matrix<T>> matrix = extractor.extract(...);
   }

我的问题是,有没有办法避免将 Matrix 定义为通用类型?我想避免的原因是“List<Attribute<T>>”在多个其他类中使用,作为私有(private)成员变量或方法返回类型。由于 Attribute,我似乎也必须将一些其他相关类定义为泛型类型,这导致了我的问题。

在这种情况下,有没有办法不将 Matrix 定义为泛型,而是将“列表”变量保留为泛型?

最佳答案

您的问题不在于通用实现,而在于它的用法:

class InfoExtractor implements Extractor{

    // The problem is actually here
    public <T> List<Matrix<T>> extract(){ 
       List<Matrix<T>> matrixList = new ArrayList<>(); //and here

        // "The problem is here!!!!"
        matrixList.add(new Matrix<String>("abc")); 
    }
}

<T>表示您正在绑定(bind)一个与方法调用相关的新泛型类型。简而言之,一个新的 T仅为此方法的执行键入。你还做了一个List<Matrix<T>>但随后尝试添加一个新的 Matrix<String>后退。如果您知道该列表将属于 Matrix<String> 类型, 那么您可以在 InfoExtractor 中指定:

//If you cannot generify the interface for some reason
interface Extractor {
    public List<? extends Matrix<?>> extract(); //explained at bottom
}

//IDEALLY, then implement Extractor<String> instead
interface Extractor<T> {
    public List<Matrix<T>> extract();
}

class InfoExtractor implements Extractor { //or Extractor<String>

    public List<Matrix<String>> extract() {
        List<Matrix<String>> matrixList = new ArrayList<>();
        matrixList.add(new Matrix<>("abc"));
        return matrixList;
    }
}

当然,你可以看到Extractor的方法签名变了。由于在返回类型上使用嵌套泛型,编译时的类型匹配会变得有点困惑。 <?>因为 Matrix 是不言自明的,我们在 Matrix 中返回多个可能未知的类型。

通过指定 ? extends MatrixExtractor ,我们正在指定适当的方差。具体的泛型是不变的,因此是List<Toyota>不是 List<Car> , 即使ToyotaCar 的子类.如果我们想要 Matrix协变,那么不幸的是我们也需要 Matrix 上的边界。这意味着实际上,忽略 Liskov 的替换原则,我们实际上是在引用提取器的具体子类( InfoExtractor ex vs Extractor ex ),尤其是从可用性的角度来看(因为具体类可以返回适当的类型安全,而接口(interface)不能)。

当然,当您指定 <T> 时,处理起来会更加理智/干净。将列表中的矩阵作为类级别的泛型类型。

关于java - 在这种情况下如何避免泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44450073/

相关文章:

javascript - JAVA 使用 Selenium 时如何禁用 Javascript?

java - 如何使用 Java 代码将 HTTP 请求默认值添加到 .jmx

java - 将 ArrayList 转换为 LinkedList

java - 使用本地类时出现错误 "illegal generic type for instanceof"

java - 使用参数指定有效的泛型类型

java - C++ 相当于使用 Entry<?扩展 A 类,? extends ClassB> getEntries() 用于两个以上的 java 参数

java - 特殊输入流,仅读取大小数组的倍数

java - 我可以在32位Windows操作系统上运行64位java程序吗

java - 带有泛型的 lambda 类型检测不正确

c# - 没有唯一键的字典