简体   繁体   English

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

[英]Java wildcard generics' return type in a method

This is perhaps the nth time I get confused about wildcards in generics so Im seeking your help. 这也许是我第九次对泛型通配符感到困惑,所以我寻求您的帮助。 Please look at the code below. 请查看下面的代码。

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

When I call m1, I can pass ArrayList<Runnable> or any of its implementing classes and it works. 当我调用m1时,我可以传递ArrayList<Runnable>或其任何实现类,并且它可以工作。 So far all is fine. 到目前为止,一切都很好。 Now within the method m1 , Im unable to return ArrayList<Thread> or ArrayList< Runnable> because the return type is Collection<T> . 现在在方法m1 ,Im无法返回ArrayList<Thread>ArrayList< Runnable>因为返回类型为Collection<T> My confusion is, T is bounded by either Runnable or any of its implementing classes and that's why I can't send ArrayList<String> when calling m1. 我的困惑是, TRunnable或其任何实现类的限制,这就是为什么在调用m1时无法发送ArrayList<String>的原因。 If the compiler is smart enough to know that, why would not it know that ArrayList<Thread> is a valid return argument for this method m1 ? 如果编译器足够聪明,知道为什么,为什么不知道ArrayList<Thread>是此方法m1的有效返回参数?

Can someone please help? 有人可以帮忙吗?

Thanks! 谢谢!

Let me explain, if compiler will allow you to return ArrayList<Thread> instead of ArrayList<T> it means you can call method with another subcalss of Runnable but still you will get ArrayList<Thread> . 让我解释一下,如果编译器允许您返回ArrayList<Thread>而不是ArrayList<T>则意味着您可以使用Runnable的另一个子级调用方法,但仍然会得到ArrayList<Thread>

For example lets say that you have another implementation of Runnable as MyThread and you are calling your method m1 as m1(new ArrayList<MyThread>) which means T=MyThread.class in the same time your method returns another implementation of Runnable ArrayList<Thread> which will lead to RuntimeException 例如,假设您有另一个Runnable实现为MyThread并且将方法m1称为m1(new ArrayList<MyThread>) ,这意味着T=MyThread.class ,同时您的方法返回了Runnable ArrayList<Thread>另一个实现ArrayList<Thread>这将导致RuntimeException

So, generics that is why here to prevent you from future runtime exceptions 因此,泛型就是这里防止您将来发生运行时异常的原因

As said by @Andy and @Michael in comments, the type of the actual variable returned should be exactly the same as the the return type defined in the function signature. 正如@Andy和@Michael在评论中所说,返回的实际变量的类型应与函数签名中定义的返回类型完全相同。

It cannot be just a subtype of it as you wrote in your code, because if a user of your function was calling it with T defined as Runnable for example, your return type just won't match the actual return type which would be Collection<Runnable> . 它不能只是您在代码中编写的子类型,因为例如,如果函数的用户使用定义为Runnable T调用它,则您的返回类型将与实际的返回类型不匹配,即Collection<Runnable>

So you should write your function like this: 因此,您应该这样编写函数:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM