Python中文网

一个关于 编程问题的解答网站.

有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何获取类(Java)中所有方法的方法引用?

Java 8中特定方法的方法参考可以通过Class::Method获得。但是如何获得一个类的所有方法的方法引用呢

所有需要的方法都有不同的方法名,但类型签名相同。此外,这些方法的名称在手前是未知的

例如:

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) { ... }
}

已知方法op0的方法参考可通过以下方式获得:

DoubleFunction<Double> f = Test::op0;

但是,如何获取类中所有方法的方法引用


共 (1) 个答案

  1. # 1 楼答案

    由于现有方法的动态发现是一种反射操作,因此没有一种解决方案可以在没有反射的情况下工作。但是,一旦发现了方法并创建了方法引用实例(或其动态等效实例),代码的实际调用将在没有反射的情况下运行:

    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);
        }
    }
    

    初始化类后,可以使用OPS.get(name).applyAsDouble(doubleValue)调用特定的操作而不进行反射,或者使用OPS.get(name).applyAsDouble(doubleValue)调用所有操作,例如

    OPS.forEach((name,op)-> System.out.println(name+'('+42+") => "+op.applyAsDouble(42)));