2016-11-20 112 views
1

考虑以下数据类型:泛型,不能转换

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; 
    } 
} 

让我们则h AVE使用的例子:

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

我们假设你是对的。 'getIntersect'方法返回'ArrayList '的实例时应该发生什么(其中'Interval2'是'IInterval '的另一个实现')? – Karol

+0

我意识到有一个问题...有关如何正确执行此操作的任何建议? –

+0

这取决于你的期望。如果将变量的类型更改为'List <? extends IInterval > intersect = t.getIntersect(1,4);'?它是否符合您的要求? – Karol

回答

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); 
}