如果希望将方法引用作为唯一输入,则可以使用以下技巧将它们调试为可打印的名称:
public static void main(String[] args) {
Person p = new Person();
Supplier nameSupplier1 = () -> "MyName";
Supplier nameSupplier2 = () -> { throw new RuntimeException(); };
set(p, Person::setName, nameSupplier1);
System.out.println(p.getName()); // prints MyName
set(p, Person::setName, nameSupplier2); // throws exception with message
System.out.println(p.getName()); // Does not execute
}
interface DebuggableBiConsumer extends BiConsumer, Serializable {}
private static void set(
E o, DebuggableBiConsumer setter, Supplier valueSupplier) {
try {
setter.accept(o, valueSupplier.get());
} catch (RuntimeException e) {
throw new RuntimeException("Failed to set the value of "+name(setter), e);
}
}
private static String name(DebuggableBiConsumer, ?> setter) {
for (Class> cl = setter.getClass(); cl != null; cl = cl.getSuperclass()) {
try {
Method m = cl.getDeclaredMethod("writeReplace");
m.setAccessible(true);
Object replacement = m.invoke(setter);
if(!(replacement instanceof SerializedLambda))
break;// custom interface implementation
SerializedLambda l = (SerializedLambda) replacement;
return l.getImplClass() + "::" + l.getImplMethodName();
}
catch (NoSuchMethodException e) {}
catch (IllegalAccessException | InvocationTargetException e) {
break;
}
}
return "unknown property";
}
局限性在于它不会为lambda表达式(对包含lambda代码的综合方法的引用)和"unknown property"接口的自定义实现打印出非常有用的方法引用。