Skip to content

Instantly share code, notes, and snippets.

@qbosen
Last active August 6, 2020 15:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save qbosen/e4cbdd18c22ffb5686c306476cd0748d to your computer and use it in GitHub Desktop.
Save qbosen/e4cbdd18c22ffb5686c306476cd0748d to your computer and use it in GitHub Desktop.
从方法引用获取属性字面值
package top.abosen.nameware;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Optional;
public class Main {
public static void main(String[] args) {
System.out.println(NameAware.nameOf(Person::getAge));
System.out.println(NameAware.nameOf(Person::setName));
System.out.println(NameAware.nameOf(Person::isMale));
// error: not a getter method
System.out.println(NameAware.nameOf(Person::toString));
}
}
@FunctionalInterface
interface Setter<T, R> extends Serializable {
void set(T receiver, R value);
}
@FunctionalInterface
interface Getter<T, R> extends Serializable {
R get(T source);
}
class Person {
private String name;
private int age;
private boolean male;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isMale() {
return male;
}
public void setMale(boolean male) {
this.male = male;
}
}
class NameAware {
public static <T, R> String nameOf(Getter<T, R> getter) {
return getLambda(getter).map(SerializedLambda::getImplMethodName)
.map(it -> normalize(it, "get", "is"))
.orElseThrow(() -> new RuntimeException("not a getter method"));
}
public static <T, R> String nameOf(Setter<T, R> setter) {
return getLambda(setter).map(SerializedLambda::getImplMethodName)
.map(it -> normalize(it, "set"))
.orElseThrow(() -> new RuntimeException("not a setter method"));
}
private static String normalize(String name, String... prefixes) {
return Arrays.stream(prefixes).filter(name::startsWith).findAny()
.map(prefix -> Character.toLowerCase(name.charAt(prefix.length())) + name.substring(prefix.length() + 1))
.orElse(null);
}
private static Optional<SerializedLambda> getLambda(Serializable func) {
try {
Method writeReplace = func.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
SerializedLambda lambda = (SerializedLambda) writeReplace.invoke(func);
return Optional.ofNullable(lambda);
} catch (Exception e) {
e.printStackTrace();
return Optional.empty();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment