I'm essentially asking the same as this old question, but for Java 14 instead of Java 8. To spare answerers the trouble of navigating to the old question, I'll rephrase it here. I want to get the name of a function from a referenced method. The following Java code should give you the idea:
public class Main
{
public static void main(String[] args)
{
printMethodName(Main::main);
}
private static void printMethodName(Consumer<String[]> theFunc)
{
String funcName = // somehow get name from theFunc
System.out.println(funcName)
}
}
The equivalent in C# would be:
public class Main
{
public static void Main()
{
var method = Main.Main;
PrintMethodName(method)
}
private static void PrintMethodName(Action action)
{
Console.WriteLine(action.GetMethodInfo().Name);
}
}
According to the accepted answer of the old question, this was not possible in Java 8 without considerable work, such as this solution. Is there a more elegant solution in Java 14?
Getting a method info from a method reference never was a goal on the JDK developer’s side, so no effort was made to change the situation.
However, the approach shown in your link can be simplified. Instead of serializing the information, patching the serialized data, and restoring the information using a replacement object, you can simply intercept the original
SerializedLambdaobject while serializing.E.g.
which will print
GetSerializedLambda main. The only newer feature used here, is theOutputStream.nullOutputStream()to drop the written information immediately. Prior to JDK 11, you could write into aByteArrayOutputStreamand drop the information after the operation which is only slightly less efficient. The example also usingvar, but this is irrelevant to the actual operation of getting the method information.The limitations are the same as in JDK 8. It requires a serializable method reference. Further, there is no guaranty that the implementation will map to a method directly. E.g., if you change the example’s declaration to
public static void main(String... args), it will print something likelambda$1when being compiled with Eclipse. When also changing the next line tovar lambda = (Consumer<String>&Serializable)GetSerializedLambda::main;, the code will always print a synthetic method name, as using a helper method is unavoidable. But in case ofjavac, the name is rather something likelambda$main$f23f6912$1instead of Eclipse’slambda$1.In other words, you can expect encountering surprising implementation details. Do not write applications relying on the availability of such information.