考虑以下数据类型:
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
,我认为这是是这样做的正确方法,但显然我错了。
有人可以解释正确的方法吗?
答案 0 :(得分:1)
首先调整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);
}