Java 具有方法调用转换的类型的多个边界

Java 具有方法调用转换的类型的多个边界,java,generics,type-erasure,Java,Generics,Type Erasure,考虑这个小测试类: import java.util.List; public abstract class Test { // CAN modify this constructor interface public <T extends Runnable & Comparable<T>> Test(List<T> l) { setList((List<Runnable>)l); // <--

考虑这个小测试类:

import java.util.List;

public abstract class Test {

    // CAN modify this constructor interface
    public <T extends Runnable & Comparable<T>> Test(List<T> l) {
        setList((List<Runnable>)l);   // <-- (a) warning
        setList(l);                   // <-- (b) error
    }

    // CANNOT modify this interface
    public abstract void setList(List<Runnable> l);
}
我在这里的理解是不能将
t
转换为
Runnable
,因为这可能被认为是一个缩小操作,但这是违反直觉的,因为
t
Runnable
Comparable
相交

在这种情况下,我必须将
T
的实例(a)转换为
List

编辑

答案是肯定的,正如Bhesh在下面指出的,泛型类型在Java中是不变的。如果我可以使用以下选项,则不会发生错误(b):

public abstract void setList(List<? extends Runnable> l);
public abstract void setList(Lista)
T
is-a
Runnable
但是
List
is-not-a
List
。泛型类型在Java中是不变的

b) 原因同上。方法参数在Java中也是不变的。(注意:方法参数是协变的。)


铸入
setList((List)l)应该是安全的,因为我们知道
T
总是实现
Runnable
。这是注释
@SuppressWarnings(“未选中”)
存在的情况类型


还有一个问题可能是(取决于您的情况)您正在从构造函数调用一个可重写的方法

public abstract void setList(List<? extends Runnable> l);