Java SerializedLambda 的 capturingClass 和 implClass 之间有什么区别?
what are the differences between capturingClass and implClass for Java SerializedLambda?
SerializedLambda的签名如下:
SerializedLambda(Class capturingClass, String functionalInterfaceClass, String functionalInterfaceMethodName, String functionalInterfaceMethodSignature, int implMethodKind, String implClass, String implMethodName, String implMethodSignature, String instantiatedMethodType, Object[] capturedArgs)
现在,我可以看到捕获 class 是一个 deserializeLambda
:
SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument
但我不明白 implClass
是干什么用的。
Get the name of the class containing the implementation method.
捕获class不就是有实现方法的吗?我尝试序列化 lambda 函数以查看这些字段包含哪些值,但它们具有相同的 class。 implClass
和 capturingClass
有什么区别?
对于当前的编译器,lambda 表达式总是在相同的 class 中编译为合成方法,包含 lambda 表达式的主体。对于那些 lambda 表达式,捕获 class 始终与“implClass”相同。
但对于不需要辅助方法的方法引用,“implClass”将是目标方法的声明 class 而捕获 class 是包含方法参考。
例如下面的例子
public class SerializedLambdaExample {
public static void main(String[] args) throws ReflectiveOperationException {
var hex = (IntFunction<String>&Serializable)Integer::toHexString;
Method m = hex.getClass().getDeclaredMethod("writeReplace");
m.setAccessible(true);
SerializedLambda sl = (SerializedLambda)m.invoke(hex);
System.out.println("cap: "+sl.getCapturingClass());
System.out.println("target: "+sl.getImplClass()+" "+sl.getImplMethodName());
}
}
打印 HotSpot/OpenJDK/javac
cap: SerializedLambdaExample
target: java/lang/Integer toHexString
但请注意,确切的形式可能取决于实现。对于方法引用,某些构造,例如涉及可变参数或交集类型,可能会使用类似于 lambda 表达式的辅助方法进行编译。理论上,包含简单方法调用的 lambda 表达式可以像方法引用一样进行编译,或者正文可以放入不同的 class,例如当 class 文件变得太大时,但这在当前编译器的实践中不会发生。
此外,不保证该示例在所有运行时都有效。仅供演示之用。
SerializedLambda的签名如下:
SerializedLambda(Class capturingClass, String functionalInterfaceClass, String functionalInterfaceMethodName, String functionalInterfaceMethodSignature, int implMethodKind, String implClass, String implMethodName, String implMethodSignature, String instantiatedMethodType, Object[] capturedArgs)
现在,我可以看到捕获 class 是一个 deserializeLambda
:
SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument
但我不明白 implClass
是干什么用的。
Get the name of the class containing the implementation method.
捕获class不就是有实现方法的吗?我尝试序列化 lambda 函数以查看这些字段包含哪些值,但它们具有相同的 class。 implClass
和 capturingClass
有什么区别?
对于当前的编译器,lambda 表达式总是在相同的 class 中编译为合成方法,包含 lambda 表达式的主体。对于那些 lambda 表达式,捕获 class 始终与“implClass”相同。
但对于不需要辅助方法的方法引用,“implClass”将是目标方法的声明 class 而捕获 class 是包含方法参考。
例如下面的例子
public class SerializedLambdaExample {
public static void main(String[] args) throws ReflectiveOperationException {
var hex = (IntFunction<String>&Serializable)Integer::toHexString;
Method m = hex.getClass().getDeclaredMethod("writeReplace");
m.setAccessible(true);
SerializedLambda sl = (SerializedLambda)m.invoke(hex);
System.out.println("cap: "+sl.getCapturingClass());
System.out.println("target: "+sl.getImplClass()+" "+sl.getImplMethodName());
}
}
打印 HotSpot/OpenJDK/javac
cap: SerializedLambdaExample
target: java/lang/Integer toHexString
但请注意,确切的形式可能取决于实现。对于方法引用,某些构造,例如涉及可变参数或交集类型,可能会使用类似于 lambda 表达式的辅助方法进行编译。理论上,包含简单方法调用的 lambda 表达式可以像方法引用一样进行编译,或者正文可以放入不同的 class,例如当 class 文件变得太大时,但这在当前编译器的实践中不会发生。
此外,不保证该示例在所有运行时都有效。仅供演示之用。