【问题标题】:How To Check If A Method Exists At Runtime In Java?如何在 Java 运行时检查方法是否存在?
【发布时间】:2011-10-26 21:09:35
【问题描述】:

如何检查 Java 中的类是否存在方法? try {...} catch {...} 声明会是好的做法吗?

【问题讨论】:

  • 你在使用反射吗?否则,我不确定你在问什么……
  • try/catch 与方法存在有什么关系?除非您指的是Iterator 接口的情况,其中remove 的实现被允许抛出UnsupportedOperationException
  • 你在说什么样的检查现有方法?反射?
  • 我正在尝试查看是否存在可能不存在的所需方法,以便我知道是否可以调用它。我想我可以将调用放在 try catch 中,如果该方法不存在则捕获错误。以防不明显,我不完全是 Java 专业人士!

标签: java methods try-catch exists


【解决方案1】:

我假设你要检查方法doSomething(String, Object)

你可以试试这个:

boolean methodExists = false;
try {
  obj.doSomething("", null);
  methodExists = true;
} catch (NoSuchMethodError e) {
  // ignore
}

这不起作用,因为该方法将在编译时解析。

您确实需要为此使用反射。如果你可以访问你要调用的方法的源代码,那么最好为你要调用的方法创建一个接口。

[更新] 附加信息是:有一个接口可能存在两个版本,一个旧版本(没有想要的方法)和一个新版本(有想要的方法)。基于此,我提出以下建议:

package so7058621;

import java.lang.reflect.Method;

public class NetherHelper {

  private static final Method getAllowedNether;
  static {
    Method m = null;
    try {
      m = World.class.getMethod("getAllowedNether");
    } catch (Exception e) {
      // doesn't matter
    }
    getAllowedNether = m;
  }

  /* Call this method instead from your code. */
  public static boolean getAllowedNether(World world) {
    if (getAllowedNether != null) {
      try {
        return ((Boolean) getAllowedNether.invoke(world)).booleanValue();
      } catch (Exception e) {
        // doesn't matter
      }
    }
    return false;
  }

  interface World {
    //boolean getAllowedNether();
  }

  public static void main(String[] args) {
    System.out.println(getAllowedNether(new World() {
      public boolean getAllowedNether() {
        return true;
      }
    }));
  }
}

这段代码测试接口中是否存在方法getAllowedNether,所以实际对象是否有方法无关紧要。

如果getAllowedNether 方法必须经常被调用并且你因此而遇到性能问题,我将不得不考虑一个更高级的答案。现在这个应该没问题。

【讨论】:

  • 该方法不在我的代码中,而是在一个链接的 jar 中——这适用吗?
  • 能说一下是什么方法吗?该方法是否来自interface,因此您可以使用instanceof 运算符简单地查询它的存在?
  • 编译器会遍历你指定的jar包并找到所有的方法,如果找不到,就会报错
  • 我将针对具有该方法的版本进行编译。它是 Bukkit (google it) 的插件,因此有带有和不带有该方法的版本 - 如果它不存在,我不需要它。不确定接口的事情 - 稍后会检查。如果是这样,那将如何工作?
  • 是的,它是一个接口 - 如果它有帮助,我正在尝试查看 github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/… 是否存在 getAllowNether() 方法(旧版本缺少它)。
【解决方案2】:

使用 Class.getMethod(...) 函数时,反射 API 会抛出 NoSuchMethodException

否则Oracle有一个很好的关于反射的教程http://download.oracle.com/javase/tutorial/reflect/index.html

【讨论】:

    【解决方案3】:

    在 java 中,这称为反射。 API 允许您发现方法并在运行时调用它们。这是指向文档的指针。这是相当冗长的语法,但它会完成工作:

    http://java.sun.com/developer/technicalArticles/ALT/Reflection/

    【讨论】:

      【解决方案4】:

      我会使用单独的方法来处理异常,并使用 null 检查来检查方法是否存在

      例如:if (null != getDeclaredMethod(obj, "getId", null)) 做你的事...

      private Method getDeclaredMethod(Object obj, String name, Class<?>... parameterTypes) {
          // TODO Auto-generated method stub
          try {
              return obj.getClass().getDeclaredMethod(name, parameterTypes);
          } catch (NoSuchMethodException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          } catch (SecurityException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          return null;
      } 
      

      【讨论】:

        【解决方案5】:

        如果您在项目中使用 Spring,您可以查看ReflectionUtil.findMethod(..)。如果方法不存在或不符合您的要求,则返回 null。 Documentation.

        【讨论】:

          【解决方案6】:

          Roland Illig 是正确的,但想添加一个示例,说明如何使用Class.getMethod 检查是否存在需要参数的方法。如果您尝试访问私有方法,也可以使用Class.getDeclaredMethod

          class World {
              public void star(String str) {}
              private void mars(String str) {}
          }
          try {
              World.class.getMethod("star", String.class);
              World.class.getDeclaredMethod("mars", String.class);
          } catch (Exception e) {}
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-17
            • 1970-01-01
            相关资源
            最近更新 更多