是否有一种方法来检查一个类是否有一个方法,然后在一个已经存在的对象实例上调用它



我有这个奇怪的情况,我想通过反射或一些库来处理,如果可能的话。是否有一种方法来检查一个类是否有一个方法,然后在一个已经存在的对象实例上调用它?

例如,假设我有:

Foo foo = new Foo();

Fooclose()方法。假设我知道很多类都有一个close()方法,但由于它们设计得很差,并且是我无法重写的遗产,我想找到一个通用的解决方案来调用我知道它们都有的方法,尽管它们不是继承自基类或接口。

我想有一个方法在我的FooHandling类接受初始化的对象,并调用他们的close()方法。这些对象绝不会从同一个基类继承,所以它们本质上是完全不同的,但都有一个具有相同名称的方法。因此,在FooHandler中,我想要这样做:

void coolGenericClosingMethod(Object o)
{
    // 1) Check via reflection if the class `o` represents contains a `close()`
    // 2) Invoke the method, if it exists, but on the passed in object `o`.
}

那么,是否有一些巧妙的技巧,我可以在一个已经实例化的对象上使用,并且仍然这样做?

有没有办法检查一个类是否有一个方法

类# getMethods ()

返回一个包含Method对象的数组,该数组反映由这个class对象表示的类或接口的所有public成员方法,包括由类或接口声明的方法和继承自超类和超接口的方法

类# getMethod(字符串,类…)

返回一个Method对象,该对象反映由这个class对象表示的类或接口的指定公共成员方法。name参数为字符串,指定the desired method的简单名称。

抛出:

NoSuchMethodException -如果没有找到匹配的方法

示例代码:

class Foo {
    public void close() {
        System.out.println("close method is invoked");
    }
}
Foo foo = new Foo();
try {
    Method m = Foo.class.getMethod("close");
    m.invoke(foo);
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}
输出:

close method is invoked

是的,你可以使用反射,就像这样

public static Object invokeIfExists(Object obj, String methodName, 
    Class<?>[] argTypes, Object[] args) throws IllegalAccessException, 
        IllegalArgumentException, InvocationTargetException {
    Method method = null;
    Object result = null;
    try {
        method = obj.getClass().getMethod(methodName, argTypes);
    } catch(NoSuchMethodException | SecurityException e) {
        // method not available in class or a security constrain has denied access
        // ignore or at least do some loggin
    }
    if(method != null) {
        result = method.invoke(obj, args);
    }
    return result;
}

获取方法对象的方法是class# getMethod(String, Class…),它允许你使用它的签名(形式参数列表)找到你正在寻找的特定方法,所以在所有重载的方法中,你得到你需要的那个。

在所有抛出的异常中,你可能最感兴趣的是InvocationTargetException,它告诉你被调用的方法抛出了一个异常。

您可以做其他人已经回答过的问题,但是如果您不想过多地使用反射,也有一些现成的选项。例如Apache Commons BeanUtils:

import org.apache.commons.beanutils.MethodUtils;
...
try {
    // 1st param: object reference
    // 2nd param: method name
    // 3rd param: args (null if no args)
    MethodUtils.invoke(obj, "close", null);
} catch (NoSuchMethodException ex) {
    // obj does not have a "close" method with no args
} catch (InvocatonTargetException ex) {
    // obj.close() was called, and threw ex.getCause()
} catch (IllegalAccessException ex) {
    // obj.close() exists, but you don't have permissions to invoke it
}
...

这些库也倾向于保持方法缓存,所以你得到快速反射;通过缓存,您可以跳过反射:方法查找的部分。

相关内容

  • 没有找到相关文章

最新更新