是否使用保证工作的反射方法检索类的泛型参数(在我的情况下)?

时间:2014-10-11 14:10:42

标签: java events generics reflection

好吧,所以我试图为自己设计一个事件系统,这就是我目前为事件处理程序所做的事情(Event是一些空类):

public interface EventHandler
{
    public Class<? extends Event> type();

    public void handle(Event event);
}

目标是EventHandler只能处理一种类型的事件(此时)。 但是,我想知道我是否可以像这样重新格式化:

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

这可以通过两种方式帮助我:

  • type()的需求消失了。
  • 在处理事件时我不必投票。

基于这个问题:Reflection for Class of generic parameter in Java?,我可以通过此方法获得T

ParameterizedType t = (ParameterizedType) MyClass.class.getGenericSuperclass(); //OtherClass<String>
Class<?> clazz = (Class<?>) t.getActualTypeArguments()[0]; // Class<String>

我知道类型擦除是处理这类事情的一个因素,但我不明白的是它何时适用于我EventHandler<T>的使用,或者几乎完全是诚实。例如,我使用EventHandler<T>的唯一方法是:

public class TestEvent extends Event {}

public class TestEventHandler implements EventHandler<TestEvent>
{
    @Override
    public void handle(TestEvent event)
    {
        System.out.println("Event Handled");
    }
}

(我的事件将在他们自己的包中,处理程序将在另一个中)

即将成为事件的总线将按类注册此处理程序,并获取它的通用事件类型,以用作事件类和EventHandler映射中的键。

无论如何,任何澄清都将不胜感激。如果我只能在一半时间内得到通用类型,那么它就不会有用,而且我可能不得不做一个没有泛型类型的版本。如果你愿意,可以随意批评如何在你的答案中开始格式化EventHandler。

2 个答案:

答案 0 :(得分:1)

这种反射技巧也用于类型标记(看起来像)。

以下是type erasure发生的例子

public class Generic<TypeParameter> {
    public void method(TypeParameter parameter) {
        // no way to know the type bound to TypeParameter due to Type Erasure
    }
} 

但它并不适用于您的案件。像

这样的声明
public class TestEventHandler extends EventHandler<TestEvent>

非常明确。它使用TestEvent作为通用EventHandler类型的类型参数。还有什么,方法声明

@Override
public void handle(TestEvent event)
{
    System.out.println("Event Handled");
}

还告诉我们该参数的类型为TestEvent。此信息不会在运行时丢失。它是Class信息的一部分(字节代码中的信息)。

如果您继续使用类似EventHandler的{​​{1}}类型,那么您将能够使用反射技巧获取TestEventHandler类型。请注意,您还可以使用匿名子类

Event

实现同样的目标。

答案 1 :(得分:0)

您展示的代码依赖MyClass作为EventHandler的直接实现类,MyClass实现EventHandler的类型参数和具体类作为类型参数。所以必须是这样的:

class MyClass implements EventHandler<String>

大多数情况下使用它(例如使用类型标记),用户应该创建一个匿名类,直接实现EventHandler<String>,如下所示:new EventHandler<String>() { /* body of anonymous class, can be empty */ },它等同于名称除了匿名部分以外的类型。

某些代码无效的情况:

  • 如果MyClass是通用的,并使用类型变量作为类型参数而不是具体类来实现EventHandler

    class MyClass<T> implements EventHandler<T>
    
  • 如果MyClass没有直接实现EventHandler,而是通过其间的一个或多个非泛型类:

    class MyClass implements YourClass
    class YourClass implements EventHandler<String>
    

(在后一种情况下,智能代码可以遍历类型层次结构以查找实现EventHandler的参数,但处理所有情况需要非常复杂,例如YourClass本身可以是通用的,并使用其中一个参数来实现EventHandler