Ant*_*ias 0 java reflection lambda java-14
我本质上是在问与这个老问题相同的问题,但针对的是 Java 14 而不是 Java 8。为了避免回答者导航到老问题的麻烦,我将在这里重新表述。我想从引用的方法中获取函数的名称。下面的 Java 代码应该能让您明白:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
C# 中的等效内容是:
public class Main
{
public static void Main()
{
var method = Main.Main;
PrintMethodName(method)
}
private static void PrintMethodName(Action action)
{
Console.WriteLine(action.GetMethodInfo().Name);
}
}
Run Code Online (Sandbox Code Playgroud)
根据老问题的公认答案,如果没有大量的工作,这在 Java 8 中是不可能的,例如这个解决方案。Java 14中有更优雅的解决方案吗?
从方法引用获取方法信息从来都不是 JDK 开发者\xe2\x80\x99s 方面的目标,因此没有做出任何努力来改变这种情况。
\n但是,您的链接中显示的方法可以简化。您可以在序列化时简单地拦截原始对象,而不是序列化信息、修补序列化数据并使用替换对象恢复信息SerializedLambda。
例如
\npublic class GetSerializedLambda extends ObjectOutputStream {\n public static void main(String[] args) { // example case\n var lambda = (Consumer<String[]>&Serializable)GetSerializedLambda::main;\n SerializedLambda sl = GetSerializedLambda.get(lambda);\n System.out.println(sl.getImplClass() + " " + sl.getImplMethodName());\n }\n\n private SerializedLambda info;\n\n GetSerializedLambda() throws IOException {\n super(OutputStream.nullOutputStream());\n super.enableReplaceObject(true);\n }\n\n @Override protected Object replaceObject(Object obj) throws IOException {\n if(obj instanceof SerializedLambda) {\n info = (SerializedLambda)obj;\n obj = null;\n }\n return obj;\n }\n\n public static SerializedLambda get(Object obj) {\n try {\n GetSerializedLambda getter = new GetSerializedLambda();\n getter.writeObject(obj);\n return getter.info;\n } catch(IOException ex) {\n throw new IllegalArgumentException("not a serializable lambda", ex);\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n将打印GetSerializedLambda main. 这里使用的唯一新功能是OutputStream.nullOutputStream()立即删除书面信息。在 JDK\xc2\xa011 之前,您可以写入 aByteArrayOutputStream并在操作后删除信息,但效率稍低。示例中也使用了var,但这与获取方法信息的实际操作无关。
限制与 JDK\xc2\xa08 中的限制相同。它需要可序列化的方法引用。此外,不保证实现将直接映射到方法。例如,如果将 example\xe2\x80\x99s 声明更改为public static void main(String... args),它将打印类似于lambda$1使用 Eclipse 编译时的内容。当还将下一行更改为 时var lambda = (Consumer<String>&Serializable)GetSerializedLambda::main;,代码将始终打印合成方法名称,因为使用辅助方法是不可避免的。但在 的情况下javac,名称更像是lambda$main$f23f6912$1Eclipse\xe2\x80\x99s lambda$1。
换句话说,您可能会遇到令人惊讶的实现细节。不要依赖此类信息的可用性来编写应用程序。
\n| 归档时间: |
|
| 查看次数: |
182 次 |
| 最近记录: |