С текущими компиляторами лямбда-выражения всегда компилируются в синтетические c методы одного и того же класса, содержащие тело лямбда-выражения. Для этих лямбда-выражений класс захвата всегда идентичен «implClass».
Но для ссылки на метод, которая не требует вспомогательного метода, «implClass» будет классом объявления целевого метода, тогда как захват 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
Но обратите внимание, что точная форма может зависеть от реализации. Для ссылок на методы некоторые конструкции, например, содержащие varargs или типы пересечений, могут быть скомпилированы с использованием вспомогательного метода, подобного лямбда-выражениям. Теоретически, лямбда-выражение, содержащее тривиальный вызов метода, может быть скомпилировано как ссылка на метод, или тело может быть помещено в другой класс, например, когда файл класса становится слишком большим, но на практике это не происходит с текущими компиляторами.
Кроме того, пример не гарантирует работу во всех средах выполнения. Это только для демонстрационных целей.