【问题标题】:Java Generic on method with Functional Interface parameter type具有功能接口参数类型的 Java 泛型方法
【发布时间】:2020-01-27 16:29:48
【问题描述】:

我不明白为什么这段代码不能编译:

package Desktop;

import java.util.function.*;

public class MyClass {

    public static <T, U> Long myMethod( Function<T, U> methodParam ) {
      return methodParam.apply("Today is happy day!");
    }

   public static void main(String[] args) {
      System.out.println( <String, Long>myMethod( Long::valueOf ) );
   }

}

所以我在控制台上收到了这个:

..\Desktop\MyClass.java:15: error: illegal start of expression
          System.out.println( <String, Long>myMethod( Long::valueOf ) );
                                            ^
..\Desktop\MyClass.java:15: error: ';' expected
          System.out.println( <String, Long>myMethod( Long::valueOf ) );
                                                                     ^
2 errors

我希望使用泛型来包含 lambda on 方法参数的类型。

【问题讨论】:

    标签: java generics lambda


    【解决方案1】:

    应该是:

    public static <T, U> U myMethod(Function<T, U> methodParam, T t) {
      return methodParam.apply(t);
    }
    
    public static void main(String[] args) {
       System.out.println(myMethod(Long::valueOf, "Today is happy day!") );
    }
    

    myMethod 接受带有泛型参数的Function,因此您不能总是使用String 参数调用其apply 方法并期望它返回Long

    相反,您可以将String 参数传递给它,并将其返回类型更改为U

    当然,这段代码会抛出 NumberFormatException,因为您无法将 String 转换为 Long

    【讨论】:

    • 2个由它产生的错误。
    • @marcius.tan 这很奇怪。我编译并执行了这段代码。正如我所说,它会引发异常,但它会通过编译。
    • public static U myMethod( Function methodParam, T t ) { return methodParam.apply(t); } public static void main(String[] args) { Long ddd = myMethod( Long::valueOf, "今天是个好日子!"); System.out.println(ddd); }
    • 我最近的回复编译但 .class 解释抛出 java.lang.NumberFormatException: For input string: "today is a good day!"
    • @marcius.tan 你不明白什么?你对Long.valueOf("Today is happy day!") 抛出异常感到惊讶吗?
    【解决方案2】:

    正如 Eran 的回答所暗示的,您有两个问题:在 myMethod 的定义和方法的调用中。

    1) 您将 methodParam 声明为输入类型为 T 和输出类型为 U 的函数。然后在 myMethod 中将其视为 T 是 String 而 U 是 Long。这只是您想要调用该方法的方式,但编译器此时对 T 和 U 一无所知。 myMethod 的 Erans 解决方案的工作原理是 myMethod 返回 U 类型的值(而不是 Long)并接收 T 类型的参数,而不是使用字符串调用 apply()。

    2) myMethod() 在 main 方法中的调用:无论是在 Erans 示例中,类型参数都由您的参数隐式给出。否则,如果您出于某种原因需要明确表达它们,@ernest_k 提供了解决方案(也找到了here)。

    【讨论】:

      【解决方案3】:

      原因是Long.valueOf() 只接受Stringlong。从类型参数T,编译器得出结论Function接受Object,因为没有Long.valueOf( Object )这样的方法,所以不会允许。

      您可能需要将myMethod() 更改为此签名:

      public static <T, U> Long myMethod( Function<String, Long> methodParam ) { //Both type parameters are explicit
          return methodParam.apply("Today is happy day!");
      }
      

      或者这个,可能会抛出NumberFormatException

      public static <T, U> Long myMethod( Function<String, U> methodParam ){ //Input  type parameter is explicit
          return (Long) methodParam.apply( "Today is happy day!" );
      }
      

      【讨论】:

        猜你喜欢
        • 2012-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多