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:
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.
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.
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.
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.
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With