1

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

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>. 我的困惑是,受其实现类中T的一个或任何一个限制,这就是为什么我在调用 m1 时Runnable无法发送。ArrayList<String>如果编译器足够聪明地知道这一点,为什么它不知道这ArrayList<Thread>是该方法的有效返回参数m1

有人可以帮忙吗?

谢谢!

4

2 回答 2

0

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

例如,假设您有 Runnable as 的另一个实现,MyThread并且您正在调用您的方法m1asm1(new ArrayList<MyThread>)这意味着T=MyThread.class在同一时间您的方法返回 Runnable 的另一个实现,ArrayList<Thread>这将导致 RuntimeException

所以,泛型就是为什么在这里防止你将来出现运行时异常

于 2018-10-30T14:54:18.947 回答
0

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

它不能只是您在代码中编写的它的子类型,因为如果您的函数的用户正在调用它并T定义Runnable为例如,您的返回类型将与实际返回类型不匹配,即Collection<Runnable>.

所以你应该这样写你的函数:

    static <T extends Runnable> Collection<T> m1(ArrayList<T> l) {
        ArrayList<T> r = new ArrayList<>();
        return r;
    }
于 2018-10-30T15:02:18.170 回答