方法中的Java通配符泛型的返回类型

时间:2018-10-30 14:39:18

标签: java generics

这也许是我第九次对泛型中的通配符感到困惑,所以我寻求您的帮助。请查看下面的代码。

public class MainClass {
    public static void main(String[] args) {
        ArrayList<Thread> l = new ArrayList<>();
        l.add(new Thread());
        l.add(new Thread());
        m1(l);
    }

     static <T extends Runnable> Collection<T> m1(ArrayList<T> l) {
        ArrayList<Thread> r = new ArrayList<>();
        return r;
    }
}

当我调用m1时,我可以传递ArrayList<Runnable>或其任何实现类,并且它可以工作。到目前为止,一切都很好。现在在方法m1中,我无法返回ArrayList<Thread>ArrayList< Runnable>,因为返回类型为Collection<T>。我的困惑是,TRunnable或其任何实现类的限制,这就是为什么我在调用m1时无法发送ArrayList<String>的原因。如果编译器足够聪明地知道这一点,为什么不知道ArrayList<Thread>是此方法m1的有效返回参数?

有人可以帮忙吗?

谢谢!

2 个答案:

答案 0 :(得分:0)

让我解释一下,如果编译器允许您返回ArrayList<Thread>而不是ArrayList<T>,则意味着您可以使用Runnable的另一个子级调用方法,但仍然会得到ArrayList<Thread>

例如,假设您有另一种Runnable实现为MyThread,并且您正在将方法m1称为m1(new ArrayList<MyThread>),这意味着T=MyThread.class是同时使用的返回Runnable ArrayList<Thread>的另一种实现,它将导致RuntimeException

因此,泛型就是为什么在这里防止您将来出现运行时异常

答案 1 :(得分:0)

如@Andy和@Michael在评论中所述,返回的实际变量的类型应与函数签名中定义的返回类型完全相同。

它不能只是您在代码中编写的子类型,因为例如,如果函数的用户使用定义为T的{​​{1}}来调用它,则返回类型就不会t匹配实际的返回类型Runnable

所以您应该这样编写函数:

Collection<Runnable>