我这里有一个Handler
类,它应该处理某种类型的Event
:
public interface Handler<E extends Event>
{
public void handle(E event);
@SuppressWarnings("unchecked")
public default Class<E> getEventType()
{
for(Method method: this.getClass().getDeclaredMethods())
{
if(method.getName().equals("handle")) return (Class<E>)method.getParameterTypes()[0];
}
throw new NullPointerException("Couldn't find the 'handle' method in this handler.");
}
}
正如您所看到的,默认情况下,只要您执行Event
,就会尝试通过返回handle()
方法的第一个参数类型来获取getEventType()
的类型(相反)到显式返回它的Handler
。这适用于以下JUnit测试:
public static class EmptyEvent extends Event
{
public void test() { }
}
public static Handler<EmptyEvent> genericHandler = new Handler<EmptyEvent>()
{
@Override
public void handle(EmptyEvent event)
{
}
};
@Test
public void testEventGenerics()
{
//prints the name of EmptyEvent
System.out.println(genericHandler.getEventType());
}
Intellij IDEA告诉我,我可以将genericHandler
简化为lambda表达式,所以我这样做:
public static class EmptyEvent extends Event
{
public void test() { }
}
public static Handler<EmptyEvent> genericHandler = event -> { };
@Test
public void testEventGenerics()
{
//prints the name of the base Event class
System.out.println(genericHandler.getEventType());
}
但是,测试会打印出Event
的名称,而不是EmptyEvent
。
所以我的问题是,有没有办法明确定义lambda表达式的泛型参数类型?
我尝试做过这样的事情,但它没有做任何事情(也是一个错误)
public static Handler<EmptyEvent> genericHandler = (EmptyEvent)event -> { };
答案 0 :(得分:4)
是的,您可以定义lambda表达式参数的类型:
public static Handler<EmptyEvent> genericHandler = (EmptyEvent event) -> { };
一般来说,没有必要,因为它是由上下文暗示的。但是,它通常使代码更容易阅读。
有关详细信息,请参阅https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27
答案 1 :(得分:1)
您正在假设lambda评估的对象的类,我不认为这些假设是有效的。 lambda覆盖handle()
方法Handler
就足够了,在运行时,handle()
方法只需Event
覆盖handle()
即可。 Handler
,在删除后Event
。无处保证lambda必须有一个handle()
方法,可以反过来说它需要EmptyEvent
。
答案 2 :(得分:0)
以下变量可能都指向同一个对象!
Handler<EventA> handlerA = event -> { };
Handler<EventB> handlerB = event -> { };
Consumer<String> consumer1 = string -> {}
Consumer<Integer> consumer2 = integer-> {}
你无法真正推断lambda表达式的确切运行时类型;唯一的保证是lambda体在运行时工作。
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27.4
[runtime]方法的主体具有评估lambda主体的效果