如何使用 Java 反射调用接受 Callable 接口或方法作为参数的方法。

huangapple go评论101阅读模式
英文:

How to Invoke a method that take a Callable Interface or method as parameter with java reflection

问题

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

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

我遇到了异常:Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch

以下展示了我的代码。

有人知道如何实现我的意图吗?

感谢您的回答!

  1. package com.helloworld;
  2. import android.annotation.TargetApi;
  3. import android.os.Build;
  4. import java.lang.reflect.Method;
  5. import java.util.concurrent.Callable;
  6. public class FinallyBlock {
  7. public static void main(String[] args) throws Exception {
  8. Method[] methods = FinallyBlock.class.getDeclaredMethods();
  9. Method templateMethod = FinallyBlock.class.getDeclaredMethod("template", Callable.class);
  10. for (Method method : methods) {
  11. if (method.getName().equals("main") || method.getName().equals("template")) {
  12. continue;
  13. }
  14. System.out.println(templateMethod.invoke(null, method));
  15. }
  16. }
  17. @TargetApi(Build.VERSION_CODES.O)
  18. private static <T> T template(Callable<T> callable) throws Exception {
  19. System.out.println("-----begin-----");
  20. System.out.println(callable.call());
  21. System.out.println("*****end*****");
  22. return null;
  23. }
  24. private static int tryThrowFinallyReturn() {
  25. try {
  26. throw new RuntimeException();
  27. } finally {
  28. return 3;
  29. }
  30. }
  31. private static int tryReturnFinallyReturn() {
  32. try {
  33. return 1;
  34. } finally {
  35. return 3;
  36. }
  37. }
  38. private static int tryCatchFinallyAllReturn() {
  39. try {
  40. return 1;
  41. } catch (Exception e) {
  42. return 2;
  43. } finally {
  44. return 3;
  45. }
  46. }
  47. private static int gotoFinallyIfMeetReturnInTry() {
  48. try {
  49. System.out.println("try_before_return");
  50. return 1;
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. } finally {
  54. return 3;
  55. }
  56. }
  57. private static int gotoFinallyIfMeetReturnInCatch() {
  58. try {
  59. throw new Exception();
  60. } catch (Exception e) {
  61. System.out.println("catch_before_return");
  62. return 2;
  63. } finally {
  64. return 3;
  65. }
  66. }
  67. private static int tryReturnFinallyNot() {
  68. try {
  69. return 1;
  70. } finally {
  71. System.out.println("finally block");
  72. }
  73. }
  74. }
英文:

Assume that I hava a Method that take Callable interface as parameters.

With java reflection.I want to invoke a method that take a method as parameter.

I got an Exception:Exception in thread &quot;main&quot; java.lang.IllegalArgumentException: argument type mismatch

Below shows my code.

Any one knows how to archive my intent?

Appreciate for you answer!

  1. package com.helloworld;
  2. import android.annotation.TargetApi;
  3. import android.os.Build;
  4. import java.lang.reflect.Method;
  5. import java.util.concurrent.Callable;
  6. /**
  7. * @author linjiejun
  8. */
  9. public class FinallyBlock {
  10. public static void main(String[] args) throws Exception {
  11. // template(FinallyBlock::tryThrowFinallyReturn);
  12. // template(FinallyBlock::tryReturnFinallyReturn);
  13. // template(FinallyBlock::tryCatchFinallyAllReturn);
  14. // template(FinallyBlock::gotoFinallyIfMeetReturnInTry);
  15. // template(FinallyBlock::gotoFinallyIfMeetReturnInCatch);
  16. Method[] methods = FinallyBlock.class.getDeclaredMethods();
  17. Method templateMethod = FinallyBlock.class.getDeclaredMethod(&quot;template&quot;, Callable.class);
  18. for (Method method : methods) {
  19. if (method.getName().equals(&quot;main&quot;) || method.getName().equals(&quot;template&quot;)) {
  20. continue;
  21. }
  22. System.out.println(templateMethod.invoke(null,method));
  23. }
  24. }
  25. @TargetApi(Build.VERSION_CODES.O)
  26. private static &lt;T&gt; T template(Callable&lt;T&gt; callable) throws Exception {
  27. System.out.println(&quot;-----begin-----&quot;);
  28. System.out.println(callable.call());
  29. System.out.println(&quot;*****end*****&quot;);
  30. return null;
  31. }
  32. // private static int tryThrowEx() {
  33. //
  34. // }
  35. //region finally 中有return 语句,try,catch block中的return,以及抛出异常都将失效。
  36. //
  37. // try 中抛出的异常,对catch依旧有效。
  38. private static int tryThrowFinallyReturn() {
  39. try {
  40. throw new RuntimeException();
  41. } finally {
  42. return 3;
  43. }
  44. }
  45. private static int tryReturnFinallyReturn() {
  46. try {
  47. return 1;
  48. } finally {
  49. return 3;
  50. }
  51. }
  52. private static int tryCatchFinallyAllReturn() {
  53. try {
  54. return 1;
  55. } catch (Exception e) {
  56. return 2;
  57. } finally {
  58. return 3;
  59. }
  60. }
  61. //endregion
  62. /**
  63. * try 中没有遇到return语句的内容会执行
  64. * try 中遇到return语句,
  65. * 就将控制权转移给
  66. * finally block
  67. *
  68. * @return
  69. */
  70. private static int gotoFinallyIfMeetReturnInTry() {
  71. try {
  72. System.out.println(&quot;try_before_return&quot;);
  73. return 1;
  74. } catch (Exception e) {
  75. e.printStackTrace();
  76. } finally {
  77. return 3;
  78. }
  79. }
  80. /**
  81. * catch block 同 try block
  82. * catch block 中没有遇到return语句的内容会执行
  83. * 遇到return语句
  84. * 就将控制权转移给
  85. * finally block
  86. *
  87. * @return
  88. */
  89. private static int gotoFinallyIfMeetReturnInCatch() {
  90. try {
  91. throw new Exception();
  92. } catch (Exception e) {
  93. System.out.println(&quot;catch_before_return&quot;);
  94. return 2;
  95. } finally {
  96. return 3;
  97. }
  98. }
  99. private static int tryReturnFinallyNot() {
  100. try {
  101. return 1;
  102. } finally {
  103. System.out.println(&quot;finally block&quot;);
  104. }
  105. }
  106. }

答案1

得分: 1

你的 template() 方法接受一个 Callable&lt;T&gt;,但你传递了一个 Method,它没有实现 Callable&lt;T&gt;,所以出现了错误。你需要实现 Callable 接口。

所以,作为建议,你可以像这样做:

1- 创建一个 Callable 类(如果你想的话,可以使用匿名类)

  1. public class MyCallableMethod implements Callable&lt;Integer&gt; {
  2. private Method m;
  3. public MyCallableMethod(Method m){
  4. this.m=m;
  5. }
  6. @Override
  7. public Integer call() throws Exception {
  8. return this.m.invoke(null);
  9. }
  10. }

2- 将

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

改为

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

当然,这只是与 "理论" 代码一起工作的示例,因为我无法编写、编译或调试代码。

另一种解决方法可能是将 template() 的签名从

  1. private static &lt;T&gt; T template(Callable&lt;T&gt; callable)

改为

  1. private static &lt;T&gt; T template(Method callable)

然后相应地更改方法体,但我相信你需要 callable 来执行某种类型的并发任务。

英文:

Your template() method accepts a Callable&lt;T&gt;, instead you pass it a Method which does not implement Callable&lt;T&gt;, thats why the error. You need to implement the Callable Interface.

So, just as suggestion you could do something like this

1- create a Callable Class (you can do an anonomus class if you want)

  1. public class MyCallableMethod implements Callable&lt;Integer&gt; {
  2. private Method m;
  3. public MyCallableMethod(Method m){
  4. this.m=m;
  5. }
  6. @Override
  7. public Integer call() throws Exception {
  8. return this.m.invoke(null);
  9. }
  10. }

2 change

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

whith

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

Of course this is just a trace of work with "theoric" code, as i cant neither write, neither compile nor debug the code.

Another solution could be change the signature of template() from

  1. private static &lt;T&gt; T template(Callable&lt;T&gt; callable)

to

  1. private static &lt;T&gt; T template(Method callable)

and change the method body accordingly, but i believe you need callable for some type of concurrent task

huangapple
  • 本文由 发表于 2020年10月24日 17:14:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/64511796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定