2014-07-03 190 views
0

我碰到了一个关于Java泛型的问题。方法不适用于Java中泛型或类型擦除的参数

我想让听众(叫SomeEventListener)听SomeEvent s发生。这些事件具有特定类型的结果;我想通过方法getResult()检索结果,其返回类型为T。当该事件被触发时,则调用eventOccurred(SomeEvent<T>)方法。

SomeEvent类:

public class SomeEvent<T> { 

    private T result; 

    public SomeEvent(T result) { 
     this.result = result; 
    } 

    public T getResult() { 
     return this.result; 
    } 
} 

SomeEventListener类:

public interface SomeEventListener<T> { 

    void eventOccurred(SomeEvent<T> event); 

} 

AnotherClass类

public class AnotherClass { 

    ArrayList<SomeEventListener<?>> listeners = new ArrayList<SomeEventListener<?>>(); 

    <T> void fireSomethingOccursEvent(SomeEvent<T> event) { 
     for (SomeEventListener<?> listener : this.listeners) { 
      listener.eventOccurred(event); // MARKED LINE 
     } 
    } 
} 

但是,嘿,Eclipse给MARKED LINE上的错误:

eventOccurred(SomeEvent < capture#2-of? >)类型SomeEventListener < capture#2-of? >是不适用的参数(SomeEvent <牛逼>)

我有犯罪嫌疑人会出现这种情况 - 它可能有事情做与泛型和类型擦除 - 但我解决不了。

我的问题:

  • 为什么上述代码无效?
  • 我该如何修复代码?

注意:有关泛型和/或类型擦除的文章很多;但是,我找不到这个问题的答案。如果您认为其他答案是合适的,请链接到它。

+0

如果您搜索类型安全的通用异质容器你可能会得到有关您的问题的东西。没有太多时间来调查问题,对不起:( –

回答

2

你有SomeEventListener<?>,具有方法void eventOccurred(SomeEvent<?> event)(代?作为T)。

对于一些完全不相关的T,您还有一个SomeEvent<T>

您不能将其转换为SomeEvent<?> - 事实上,除null之外,您无法将任何东西转换为SomeEvent<?>?的意思是“我不知道这种类型的论点是什么。”

举个例子,如果你的代码是允许的,这段代码编译,但传递了错误的类型:

AnotherClass ac = new AnotherClass(); 

ac.listeners.add(new SomeEventListener<Integer>() { 
    void eventOccurred(SomeEvent<Integer> event) { 
     System.out.println(event.intValue()); 
    } 
}); 

SomeEvent<String> event = new SomeEvent<String>("Hello"); 
ac.fireSomethingOccursEvent(event); 

现在fireSomethingOccursEvent将采取SomeEvent<String>并将它传递给一个SomeEventListener<Integer>。这显然不应该被允许 - 所以,这是不允许的。

0

可以使整个AnotherClass通用和使用wildcards

public class AnotherClass<T> { 

    ArrayList<SomeEventListener<? super T>> listeners = new ArrayList<>(); 
    //use diamond-type since java 1.7 

    void fireSomethingOccursEvent(SomeEvent<? extends T> event) { 
     for (SomeEventListener<? super T> listener : this.listeners) { 
      listener.eventOccurred(event); // should be fine 
     } 
    } 
}