Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the name of the method resulting from a lambda

Tags:

lambda

java-8

From a simple point of view, lambda expressions are compiled into static methods, since they don’t capture this (i.e. do not access instance members).

public class App {
  public static void foo(){
      Consumer<Integer> c1 = n -> {};
      Consumer<Integer> c2 = n -> {};
  }

  public static void main(String [] args) {
    Supplier<String> sup1 = () -> "I am sup1";
    Supplier<String> sup2 = () -> "I am sup2";
    Supplier<String> sup3 = () -> "I am sup3";

    Stream.of(App.class.getDeclaredMethods()).forEach(System.out::println);
  }
}

Running the previous example and checking the generated bytecodes with the javap tool, we can see that lambdas referred by variables c1, c2, sup1, sup2, sup3 are compiled to methods with names:

  • lambda$foo$0
  • lambda$foo$1
  • lambda$main$2
  • lambda$main$3
  • lambda$main$4

However, if we print the getClass() for each object referred by those variables (c1, c2, sup1, sup2, sup3) we will get, respectively:

  • class App$$Lambda$5/1705736037
  • class App$$Lambda$6/455659002
  • class App$$Lambda$1/791452441
  • class App$$Lambda$2/531885035
  • class App$$Lambda$3/1418481495

So, how can we make the correspondence between the runtime class names and the name of the methods resulting from the lambdas?

UPDATE

None of the solutions pointed in the following duplicated questions helps me to solve the problem that I am asking in my question:

  • How to get the MethodInfo of a Java 8 method reference?
  • Printing debug info on errors with java 8 lambda expressions 1 answer
  • Get MethodHandle from lambda object

The only way that I found was to adapt the solution of @Holger from its answer (not the accepted one) to the question Java 8: convert lambda to a Method instance with clousure included. However, in my case, instead of a Method object I am just looking for the name of the method. So, adapting that lambdaToMethod() to the following methodNameFromLambda() I got a solution:

static String methodNameFromLambda(Serializable lambda) {
  try {
    Method m = lambda.getClass().getDeclaredMethod("writeReplace");
    m.setAccessible(true);
    SerializedLambda sl=(SerializedLambda)m.invoke(lambda);
    return sl.getImplMethodName();
  } catch(ReflectiveOperationException ex) {
    throw new RuntimeException(ex);
  }
}

Now, lambdas of the example must be cast to Consumer<Integer>&Serializable or Supplier<String>&Serializable as describe in @Holger answer.

I am not aware if this solution is correct, but it works for my example and for the cases that I am working on.

like image 966
Miguel Gamboa Avatar asked Nov 15 '17 17:11

Miguel Gamboa


People also ask

How do you convert lambda expression to method?

To make the code clearer, you can turn that lambda expression into a method reference: Consumer<String> c = System. out::println; In a method reference, you place the object (or class) that contains the method before the :: operator and the name of the method after it without arguments.

Can lambda expression have name?

Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

How do you call a method in lambda?

You can invoke Lambda functions directly using the Lambda console, a function URL HTTP(S) endpoint, the Lambda API, an AWS SDK, the AWS Command Line Interface (AWS CLI), and AWS toolkits.

How do you call a default method using lambda expression?

Default methods can be used in lambda expressions. Formula formula = (a) -> sqrt( a * 100); is to define a Formula , which works as functional interface, directly via a lambda expression. Formula formula = (a) -> sqrt( a * 100);


1 Answers

This is subject to change from version to version - there is no specification that says what the exact names would be - and it's done on purpose; well to protect against code that might find clever things to do with these names.

like image 122
Eugene Avatar answered Nov 15 '22 08:11

Eugene