Forked from thomasdarimont/ExtractOriginalMethodNameFromReferenceExample.java
Created
June 1, 2018 22:24
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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