通用类型与方法引用配对

时间:2018-12-20 21:48:22

标签: generics lambda enums java-8 java-stream

我偶然发现了这个。这是短篇小说。在某些代码库中,有一堆遵循相同模式的枚举,下面是一个大大简化的枚举:

enum Letters {
    A("a"),
    Z("z");

    private String value;

    Letters(String value) {
        this.value = value;
    }

    private static final Map<String, Letters> MAP;

    public String getValue() {
        return value;
    }

    static {
        MAP = Arrays.stream(values())
                    .collect(Collectors.collectingAndThen(
                        Collectors.toMap(
                            Letters::getValue,
                            Function.identity()
                        ),
                        ImmutableMap::copyOf
                    ));
    }

    public static Optional<Letters> fromValue(String value) {
        return Optional.ofNullable(MAP.get(value));
    }
}

从字面上看,这是一个跨越数十个Enum的模式,没有,这是无法更改的。我考虑过更改此代码重复,因为它重复了很多。

我的想法是从一个枚举接口开始,所有接口都将实现:

interface GetValueInterface {
    String getValue();
}

还有一些可以处理此MAP创建的通用代码(fromValue也可以在那里处理,但我们将其放在一边)。所以,像这样:

 static class EnumsCommon {

    public static <T extends Enum<T> & GetValueInterface> Map<String, T> getAsMap(Class<T> clazz) {
        T[] values = clazz.getEnumConstants();

        return Arrays.stream(values)
                     .collect(Collectors.collectingAndThen(
                         Collectors.toMap(
                             T::getValue,
                             Function.identity()
                         ),
                         ImmutableMap::copyOf
                     ));
    }
}

所以代码现在看起来像这样:

enum Letters implements GetValueInterface {

    // everything else stays the same
    static {
        MAP = EnumsCommon.getAsMap(Letters.class);
    }
}

这可以正常编译,但是当我在java-8下运行时,会抛出异常:

  

原因:java.lang.invoke.LambdaConversionException:无效的接收者类型类java.lang.Enum;不是实现类型接口GetValueInterface的子类型

java-11下运行相同的代码就可以了...

1 个答案:

答案 0 :(得分:2)

准备好此问题20分钟后,我进行了一次Google搜索,并立即发现了问题:| this one

修复很容易,只需使用lambda表达式即可:

(T t) -> t.getValue() // instead of T::getValue