Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save functicons/ce23dc661a3eb7a604eb915c364b1234 to your computer and use it in GitHub Desktop.
Save functicons/ce23dc661a3eb7a604eb915c364b1234 to your computer and use it in GitHub Desktop.
One can use a SerializedLambda to unreflect the actual method referred to by a MethodReference
package de.tdlabs.training.hacks;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Supplier;
import static java.util.Arrays.asList;
/**
* Created by tom on 25.04.16.
*/
public class ExtractOriginalMethodNameFromReferenceExample {
public static void main(String[] args) {
BusinessObject bo = new BusinessObject();
System.out.println(printPropertyName(bo::getProperty1));
System.out.println(printPropertyName(bo::getProperty2));
System.out.println(printPropertyName(bo::setProperty1));
System.out.println(printPropertyName(bo::setProperty2));
}
private static <T> String printPropertyName(SerializableSupplier<T> getter) {
return getter.method().getName();
}
private static <T> String printPropertyName(SerializableConsumer<T> setter) {
return setter.method().getName();
}
interface MethodReferenceReflection {
//inspired by: http://benjiweber.co.uk/blog/2015/08/17/lambda-parameter-names-with-reflection/
default SerializedLambda serialized() {
try {
Method replaceMethod = getClass().getDeclaredMethod("writeReplace");
replaceMethod.setAccessible(true);
return (SerializedLambda) replaceMethod.invoke(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
default Class<?> getContainingClass() {
try {
String className = serialized().getImplClass().replaceAll("/", ".");
return Class.forName(className);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
default Method method() {
SerializedLambda lambda = serialized();
Class<?> containingClass = getContainingClass();
return asList(containingClass.getDeclaredMethods())
.stream()
.filter(method -> Objects.equals(method.getName(), lambda.getImplMethodName())) //TODO check parameter types to deal with overloads
.findFirst()
.orElseThrow(UnableToGuessMethodException::new);
}
class UnableToGuessMethodException extends RuntimeException {
}
}
interface SerializableSupplier<T> extends Supplier<T>, Serializable, MethodReferenceReflection {
}
interface SerializableConsumer<T> extends Consumer<T>, Serializable, MethodReferenceReflection {
}
static class BusinessObject {
private String property1;
private int property2;
public String getProperty1() {
return property1;
}
public void setProperty1(String property1) {
this.property1 = property1;
}
public int getProperty2() {
return property2;
}
public void setProperty2(int property2) {
this.property2 = property2;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment