简体   繁体   English

为什么这个泛型方法不接受任何类型?

[英]Why doesn't this generic method accept any type?

In the code below, when I call getList() I am not able to specify <T> . 在下面的代码中,当我调用getList()我无法指定<T> getList<T>() does not compile. getList<T>()不编译。

Instead, I may only call getList() - but then <T> is always simply <Event> . 相反,我可能只调用getList() - 但<T>总是只是<Event>

Why is this? 为什么是这样?

class Foo
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // For the sake of a complete example - the next method has
        // my question.
        Foo f = new Foo();
        f.register(new Subscriber<MyEvent>() {
            public void handle(MyEvent event){};
        });
    }

    public <T extends Event> void register(Subscriber<T> subscriber) {

        // Below won't work. I can't specify <T>, so getList()
        // will return a HashSet<Subscriber<Event>>, to which I cannot
        // add the Subscriber<T>!

        getList().add(subscriber);

        // Why can't I call getList<T>().add(subscriber) ?

    }

    private <T extends Event> HashSet<Subscriber<T>> getList() {
        // For the sake of example, simply return a new HashSet.
        return new HashSet<Subscriber<T>>();
    }
}

interface Subscriber<T extends Event> {
    public void handle(T event);
}

interface Event { }
class MyEvent implements Event { }

It appears that Java won't accept a <T> as the type argument to a simple name such as getList() . Java似乎不接受<T>作为简单名称(如getList()的类型参数。 But it will accept it if you explicitly state this. 但如果你明确说明this.它会接受它this. when calling the method: 在调用方法时:

this.<T>getList().add(subscriber);

I believe the right answer is to make Foo into Foo<T extends Event> so that when in Foo T is defined. 我相信正确的答案是让Foo成为Foo<T extends Event>以便在定义Foo T时。

Otherwise, try this.<T>getList() . 否则,试试this.<T>getList() This is how this is done for statics MyClass.<String>someMethod() . 这是静态MyClass.<String>someMethod() Not sure if it will also work for an instance method. 不确定它是否也适用于实例方法。 Again, the best answer is to make Foo generic. 同样,最好的答案是让Foo变得通用。

The T from you example is extending Event in both methods of Foo class. 你的例子中的T是在Foo类的两个方法中扩展Event Well that implicitly means you Foo class is working only with <T extends Event> type inference. 好吧, 隐含意味着你Foo类只与<T extends Event>类型推断一起工作。 Unfortunately, your T is defined only at method scope. 不幸的是,您的T仅在方法范围内定义。 For humans all looks alright. 对于人类来说,所有人看起 But compiler is a bit different. 但编译器有点不同。 Compiler doesn't believe you and it's not able to figure out implicit informations, however they are just fine, logically. 编译器不相信你,也无法找出隐含的信息,但它们在逻辑上也很好。 You did not define your T at Class scope and the compiler did not figure out you are using the same type inference in both methods. 您没有在Class范围内定义T ,并且编译器没有发现您在两种方法中都使用相同的类型推断。 So, compiler wont let you mix these method together. 所以,编译器不会让你把这些方法混合在一起。

So, the solution should explicitly define type inference is for Class scope use not only for method scope. 因此,解决方案应该明确定义类型推断是针对类范围使用的,不仅仅是方法范围。

class Foo<T extends Event>
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // For the sake of a complete example - the next method has
        // my question.
        Foo<MyEvent> f = new Foo<MyEvent>();
        f.register(new Subscriber<MyEvent>() {
            public void handle(MyEvent event){};
        });
    }

    public void register(Subscriber<T> subscriber) {

        // Below won't work. I can't specify <T>, so getList()
        // will return a HashSet<Subscriber<Event>>, to which I cannot
        // add the Subscriber<T>!

        getList().add(subscriber);

        // Why can't I call getList<T>().add(subscriber) ?

    }

    private HashSet<Subscriber<T>> getList() {
        // For the sake of example, simply return a new HashSet.
        return new HashSet<Subscriber<T>>();
    }

}

interface Subscriber<T extends Event> {
    public void handle(T event);
}

 class MyEvent extends Event {

}
 class Event {

}

Perhaps you need to be a little more gentle with Java. 也许你需要对Java更温和一点。 This seems to work without warnings: 这似乎没有警告:

HashSet<Subscriber<T>> list = getList();
list.add(subscriber);

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

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