问题
Method Reference for a specific method in Java 8 can be obtained as Class::Method
. But how to get the method reference of all methods of a class?
All the desired methods have different method names, but the same type signature. Also, the names of the methods is not known before hand.
Example:
class Test {
public static double op0(double a) { ... }
public static double op1(double a) { ... }
public static double op2(double a) { ... }
public static double op3(double a) { ... }
public static double op4(double a) { ... }
}
The method reference to a known method op0
can be obtained as:
DoubleFunction<Double> f = Test::op0;
But, how to get the method references of all methods in the class?
回答1:
There is no solution that works without Reflection as the dynamic discovery of existing methods is a reflective operation. However, once methods are discovered and a method reference instance (or the dynamic equivalent of it) has been created, the actual invocation of the code runs without Reflection:
class Test {
public static double op0(double a) { ... }
public static double op1(double a) { ... }
public static double op2(double a) { ... }
public static double op3(double a) { ... }
public static double op4(double a) { ... }
static final Map<String, DoubleUnaryOperator> OPS;
static {
HashMap<String, DoubleUnaryOperator> map=new HashMap<>();
MethodType type=MethodType.methodType(double.class, double.class);
MethodType inT=MethodType.methodType(DoubleUnaryOperator.class);
MethodHandles.Lookup l=MethodHandles.lookup();
for(Method m:Test.class.getDeclaredMethods()) try {
if(!Modifier.isStatic(m.getModifiers())) continue;
MethodHandle mh=l.unreflect(m);
if(!mh.type().equals(type)) continue;
map.put(m.getName(), (DoubleUnaryOperator)LambdaMetafactory.metafactory(
l, "applyAsDouble", inT, type, mh, type).getTarget().invokeExact());
} catch(Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
OPS=Collections.unmodifiableMap(map);
}
}
Once the class has been initialized, you can invoke a particular op without Reflection using OPS.get(name).applyAsDouble(doubleValue)
or invoke all ops using, e.g.
OPS.forEach((name,op)-> System.out.println(name+'('+42+") => "+op.applyAsDouble(42)));
来源:https://stackoverflow.com/questions/29347434/how-to-get-method-reference-for-all-methods-in-a-class-java