如何使用Java反射调用将可调用接口或方法作为参数的方法

问题描述

假设我有一个以Callable接口作为参数的方法。

使用Java反射。我想调用一个以method作为参数的方法。

我有一个例外:Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch

下面显示了我的代码。

有人知道如何存档我的意图吗?

感谢您的回答!

package com.helloworld;

import android.annotation.TargetApi;
import android.os.Build;

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

/**
 * @author linjiejun 
 */
public class FinallyBlock {
    public static void main(String[] args) throws Exception {
//        template(FinallyBlock::tryThrowFinallyReturn);
//        template(FinallyBlock::tryReturnFinallyReturn);
//        template(FinallyBlock::tryCatchFinallyAllReturn);
//        template(FinallyBlock::gotoFinallyIfMeetReturnInTry);
//        template(FinallyBlock::gotoFinallyIfMeetReturnInCatch);
        
        Method[] methods = FinallyBlock.class.getDeclaredMethods();
        Method templateMethod = FinallyBlock.class.getDeclaredMethod("template",Callable.class);
        for (Method method : methods) {
            if (method.getName().equals("main") || method.getName().equals("template")) {
                continue;
            }
            System.out.println(templateMethod.invoke(null,method));
        }
    }

    @TargetApi(Build.VERSION_CODES.O)
    private static <T> T template(Callable<T> callable) throws Exception {
        System.out.println("-----begin-----");
        System.out.println(callable.call());
        System.out.println("*****end*****");

        return null;
    }

//    private static int tryThrowEx() {
//
//    }

    //region finally 中有return 语句,try,catch block中的return,以及抛出异常都将失效。
    //
    // try 中抛出的异常,对catch依旧有效。
    private static int tryThrowFinallyReturn() {
        try {
            throw new RuntimeException();
        } finally {
            return 3;
        }
    }

    private static int tryReturnFinallyReturn() {
        try {
            return 1;
        } finally {
            return 3;
        }
    }

    private static int tryCatchFinallyAllReturn() {
        try {
            return 1;
        } catch (Exception e) {
            return 2;
        } finally {
            return 3;
        }
    }
    //endregion

    /**
     * try 中没有遇到return语句的内容会执行
     * try 中遇到return语句,
     * 就将控制权转移给
     * finally block
     *
     * @return
     */
    private static int gotoFinallyIfMeetReturnInTry() {
        try {
            System.out.println("try_before_return");
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return 3;
        }
    }

    /**
     * catch block 同 try block
     * catch block 中没有遇到return语句的内容会执行
     * 遇到return语句
     * 就将控制权转移给
     * finally block
     *
     * @return
     */
    private static int gotoFinallyIfMeetReturnInCatch() {
        try {
            throw new Exception();
        } catch (Exception e) {
            System.out.println("catch_before_return");
            return 2;
        } finally {
            return 3;
        }
    }

    private static int tryReturnFinallyNot() {
        try {
            return 1;
        } finally {
            System.out.println("finally block");
        }
    }
}

解决方法

您的template()方法接受一个Callable<T>,而您向它传递了一个未实现Method的{​​{1}},这就是错误的原因。您需要实现Callable Interface。

所以,正如您建议的那样,您可以做这样的事情

1-创建一个Callable类(如果需要,可以创建一个匿名类)

Callable<T>

2次更改

public class MyCallableMethod implements Callable<Integer> {

    private Method m;

    public MyCallableMethod(Method m){
       this.m=m;
    }
    @Override
    public Integer call() throws Exception {
        return this.m.invoke(null);
    }
}

还有

System.out.println(templateMethod.invoke(null,method));

当然,这只是使用“理论”代码的痕迹,因为我既不能编写代码,也不能编译或调试代码。

另一种解决方案是将template()的签名更改为

System.out.println(templateMethod.invoke(null,new MyCallableMethod(method)));

 private static <T> T template(Callable<T> callable)

并相应地更改方法主体,但是我相信您需要某种类型的并发任务可调用

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...