gpt4 book ai didi

java-8 - 对原始类型的方法引用有害吗?

转载 作者:行者123 更新时间:2023-12-03 17:08:56 25 4
gpt4 key购买 nike

下面的代码包含对 Enum::name 的引用(注意没有类型参数)。

public static <T extends Enum<T>> ColumnType<T, String> enumColumn(Class<T> klazz) {
return simpleColumn((row, label) -> valueOf(klazz, row.getString(label)), Enum::name);
}

public static <T, R> ColumnType<T, R> simpleColumn(BiFunction<JsonObject, String, T> readFromJson,
Function<T, R> writeToDb) {
// ...
}

Javac 编译时报警告:

[WARNING] found raw type: java.lang.Enum missing type arguments for generic class java.lang.Enum



将表达式更改为 Enum<T>::name导致警告消失。

然而,Idea 标记了 Enum<T>::name带有警告的版本:

Explicit type arguments can be inferred



反过来,Eclipse (ECJ) 没有报告任何一种配方的任何问题。

三种方法中哪一种是正确的?

一方面,原始类型相当讨厌。如果您尝试放置一些其他类型的参数,例如 Enum<Clause>::name会导致编译失败,所以这是一些额外的保护。

另一方面,上述引用等效于 e -> e.name() lambda,并且这个公式不需要类型参数。

环境:
  • Java 8u91
  • IDEA 15.0.3 社区
  • 欧洲法院 4.5.2
  • 最佳答案

    没有“原始方法引用”这样的东西。虽然原始类型的存在是为了帮助迁移 pre-Generics 代码,但不能有任何 pre-Generics 使用方法引用,因此没有“兼容模式”,类型推断是常态。 Java Language Specification §15.13. Method Reference Expressions状态:

    If a method or constructor is generic, the appropriate type arguments may either be inferred or provided explicitly. Similarly, the type arguments of a generic type mentioned by the method reference expression may be provided explicitly or inferred.

    Method reference expressions are always poly expressions


    所以虽然你可以在 :: 之前调用类型一个“原始类型”当它引用一个泛型类而不指定类型参数时,编译器仍然会根据目标函数类型推断泛型类型签名。这就是为什么在此处生成有关“原始类型使用”的警告没有意义的原因。
    请注意,例如
    BiFunction<List<String>,Integer,String> f1 = List::get;
    Function<Enum<Thread.State>,String> f2 = Enum::name;
    可以用 javac 编译没有任何警告(规范命名了应该推断类型的类似示例),而
    Function<Thread.State,String> f3 = Enum::name;
    生成警告。 specification says关于这个案例:

    In the second search, if P1, ..., Pn is not empty and P1 is a subtype of ReferenceType, then the method reference expression is treated as if it were a method invocation expression with argument expressions of types P2, ..., Pn. If ReferenceType is a raw type, and there exists a parameterization of this type, G<...>, that is a supertype of P1, the type to search is the result of capture conversion (§5.1.10) applied to G<...>;…


    所以在上面的例子中,编译器应该推断 Enum<Thread.State>作为 Enum的参数化那是 Thread.State 的父类(super class)型搜索适当的方法并得到与 f2 相同的结果例子。它以某种方式确实有效,但它会生成无意义的原始类型警告。

    显然, javac只有在必须搜索适当的父类(super class)型时才会生成此警告,对于您的情况,有一个简单的解决方案。只需使用确切类型进行搜索:
    public static <T extends Enum<T>> ColumnType<T, String> enumColumn(Class<T> klazz) {
    return simpleColumn((row, label) -> valueOf(klazz, row.getString(label)), T::name);
    }
    这将在没有任何警告的情况下编译。

    关于java-8 - 对原始类型的方法引用有害吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37185734/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com