SerializedLambda的签名如下:

SerializedLambda(类捕获类,字符串functionalInterfaceClass,字符串functionalInterfaceMethodName,字符串functionalInterfaceMethodSignature,int implMethodKind,字符串implClass,字符串implMethodName,字符串implMethodSignature,字符串instantiatedMethodType,Object [] captureArgs)

现在,我可以看到捕获类是带有deserializeLambda的类:

SerializedLambda有一个readResolve方法,该方法在捕获类中查找称为$ deserializeLambda $(SerializedLambda)的(可能是私有的)静态方法,并以其自身作为第一个参数进行调用

但是我没有得到implClass的用途。

获取包含实现方法的类的名称。

捕获类不是实现方法中的一种吗?我尝试序列化lambda函数,以查看这些字段包含哪些值,但它们具有相同的类。 implClasscapturingClass有什么区别?

最佳答案

在当前的编译器中,lambda表达式始终在同一类中编译为合成方法,并保留lambda表达式的主体。对于那些lambda表达式,捕获类始终与“implClass”相同。

但是对于不需要辅助方法的方法引用,“implClass”将是目标方法的声明类,而捕获类是包含该方法引用的类。

例如,以下示例

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表达式可以像方法引用一样进行编译,或者可以将主体置于不同的类中,例如当类文件变得太大时,但是在当前的编译器中实际上不会发生这种情况。

另外,不能保证该示例在所有运行时中都能正常工作。仅用于演示目的。

10-06 15:36