java - 带有捕获的泛型,无法转换

标签 java generics

考虑以下数据类型:

import java.util.ArrayList;
import java.util.List;

public class MyList<T extends Comparable<T>> {
  protected List<T> data = new ArrayList<>();

  public void add(T v) {
    data.add(v);
  }
}

让我们定义一个通用的区间数据类型:

public interface IInterval<T extends Comparable<T>> extends Comparable<IInterval<T>> {

  T getBegin();

  T getEnd();

  @Override
  default public int compareTo(IInterval<T> other) {
    int c1 = getEnd().compareTo(other.getEnd());
    if (c1 == 0) {
      return getBegin().compareTo(other.getBegin());
    } else
      return c1;
  }
}

假设我们要扩展MyList保存间隔,并有一个返回与特定范围相交的间隔的方法:

import java.util.ArrayList;
import java.util.List;

public class MyIntervalList<T extends Comparable<T>> extends MyList<IInterval<T>> {

  public List<? extends IInterval<T>> getIntersect(T begin, T end) {
    List<IInterval<T>> res = new ArrayList<>();
    for (IInterval v : data) {
      if (v.getEnd().compareTo(begin) < 0 ||
          v.getBegin().compareTo(end) > 0) {
        res.add(v);
      }
    }
    return res;
  }
}

让我们看一个使用示例:

import java.util.List

class Interval implements IInterval<Integer> {
  private int begin, end;

  public Interval(int begin, int end) {
    this.begin = begin;
    this.end = end;
  }

  public Integer getBegin() {
    return begin;
  }

  public Integer getEnd() {
    return end;
  }
}

public class Test {
  public static void main(String[] args) {
    MyIntervalList<Integer> t = new MyIntervalList<>();
    t.add(new Interval(1, 10));

    List<Interval> l = t.getIntersect(1, 4);
  }
}

当我编译这个时,我收到错误:

Test.java:8: error: incompatible types: List<CAP#1> cannot be converted to List<Interval>
    List<Interval> l = t.getIntersect(1, 4);
                                     ^
  where CAP#1 is a fresh type-variable:
    CAP#1 extends IInterval<Integer> from capture of ? extends IInterval<Integer>
1 error

Interval实现IInterval<Integer>getIntersect被声明为返回 ? extends IInterval<T> ,其中Integer已传递为 T ,我认为这是正确的方法,但显然我错了。

谁能解释一下正确的方法吗?

最佳答案

首先调整MyList以允许它接受任何内容(不需要将类型限制为Comparable):

class MyList<T> { 
    protected List<T> data = new ArrayList<>();

    public void add(T v) {
        data.add(v);
    }
}

然后更改MyIntervalList的签名以指定其包含的间隔类型:

class MyIntervalList<T extends Comparable<T>, I extends IInterval<T>> extends MyList<I> {
    public List<I> getIntersect(T begin, T end) {
        List<I> res = new ArrayList<>();
        for (I v : data) {
            if (v.getEnd().compareTo(begin) < 0 ||
                v.getBegin().compareTo(end) > 0) {
                res.add(v);
            }
        }
        return res;
    }
}

现在编译器可以知道它正在处理什么类型的间隔,并且会很高兴:

public static void main(String[] args) {
    MyIntervalList<Integer, Interval> t = new MyIntervalList<>();
    t.add(new Interval(1, 10));
    List<Interval> intersect = t.getIntersect(1, 4);
}

关于java - 带有捕获的泛型,无法转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40699639/

相关文章:

c# - 是否有 .Net C# 探查器可以针对泛型方法的不同类型执行报告单独的统计信息?

java - 无法创建通用数组

java - 在 ArrayList 中找不到对象

java - SSL 问题 java web 应用程序

java - 华盛顿驾照的正则表达式模式?

generics - 有没有办法确定 Lua 函数的签名?

java - 使用泛型动态实例化类型

c# - 如何从具有基本类型约束的泛型方法中获取 typeof(T)?

java - 将扫描仪中的单词处理为字符串数组

java - 计算小于 N 的以 2 为底的对数的最大整数