Я не могу понять, почему этот код не компилируется:

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

Я ожидаю использовать обобщения для включения типа для лямбда-параметра метода.

0
marcius.tan 27 Янв 2020 в 11:00

3 ответа

Лучший ответ

Должен быть:

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 с общими параметрами, поэтому вы не всегда можете вызвать его метод apply с аргументом String и ожидать, что он вернет Long.

Вместо этого вы можете передать ему аргумент String и изменить его тип возвращаемого значения на U.

Конечно, этот код выдаст NumberFormatException, так как вы не можете преобразовать это String в Long.

5
Eran 27 Янв 2020 в 08:04

Как следует из ответа Эрана, у вас есть две проблемы: в определении myMethod и в вызове метода.

1) Вы объявляете methodParam как функцию с типом ввода T и типом вывода U. А затем в myMethod вы обрабатываете его так, как если бы T было String, а U - Long. Это только то, как вы хотите вызвать метод, но компилятор ничего не знает о T и U на данный момент. Решение Erans для myMethod работает так, как myMethod возвращает значение типа U (вместо Long) и получает параметр типа T вместо вызова apply () со строкой.

2) Вызов myMethod () в основном методе: либо как в примере с Erans, параметры типа неявно задаются вашими параметрами. В противном случае, если вам необходимо выразить их явно по какой-то причине, @ernest_k показал решение (также найдено здесь ) .

1
Matthias Heinlein 27 Янв 2020 в 08:21

Причина в том, что Long.valueOf() принимает только String или long. Из параметра типа 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!" );
}
1
Sree Kumar 27 Янв 2020 в 08:29