有没有办法在lambda表达式中显式定义泛型参数类型?

oct*_*pod 9 java generics lambda

我这里有一个Handler类,它应该处理Event某种类型的s:

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.");
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,默认情况下,它会尝试通过在执行时Event返回方法的第一个参数类型来获取类型(而不是显式返回它).这适用于以下JUnit测试:handle()getEventType()Handler

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());
}
Run Code Online (Sandbox Code Playgroud)

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());
}
Run Code Online (Sandbox Code Playgroud)

但是,测试打印出的名称Event,而不是EmptyEvent.

所以我的问题是,有没有办法明确定义lambda表达式的泛型参数类型?

我尝试过做这样的事情,但它没有做任何事情(也是一个错误)

public static Handler<EmptyEvent> genericHandler = (EmptyEvent)event -> { };
Run Code Online (Sandbox Code Playgroud)

spr*_*ter 5

是的,您可以定义lambda表达式参数的类型:

public static Handler<EmptyEvent> genericHandler = (EmptyEvent event) -> { };
Run Code Online (Sandbox Code Playgroud)

通常,由于上下文暗示它是没有必要的。但是,这通常会使代码更易于阅读。

有关更多详细信息,请参见https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27