繁体   English   中英

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

[英]Is there a way to check if a class has a method and then invoke it on an already existing instance of the object?

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

例如,假设我有:

Foo foo = new Foo();

Foo有一个close()方法。 假设我知道很多类都有一个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参数是一个String,指定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
}
...

这些库也倾向于保留方法缓存,因此您可以快速反映; 通过缓存,您可以跳过反射的缓慢部分:方法查找。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM