2016-11-20 116 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); 
}