简体   繁体   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?

I have this odd case which I'd like to handle through reflection or some library, if possible. 我有这个奇怪的案例,如果可能的话,我想通过反思或某些库来处理。 Is there a way to check if a class has a method and then invoke it on an already existing instance of the object? 有没有办法检查一个类是否有一个方法,然后在已经存在的对象实例上调用它?

For example, let's say I have: 例如,假设我有:

Foo foo = new Foo();

Foo has a close() method. Foo有一个close()方法。 Let's say I know that a lot of the classes will have a close() method but since they were poorly devised and are legacy that I cannot re-write, I would like to find out a generic solution to invoke a method I know they all have, despite them not inheriting from a base class or interface. 假设我知道很多类都有一个close()方法,但由于它们设计得很差并且是我无法重写的遗留问题,我想找出一个通用的解决方案来调用我知道它们的方法尽管它们不是从基类或接口继承的。

I would like to have a method in my FooHandling class that accepts initialized objects and invokes their close() method. 我想在我的FooHandling类中有一个方法接受初始化对象并调用它们的close()方法。 The objects will by no means inherit from the same base class, so they're totally different in nature, but all have a method with the same name. 对象绝不会继承自同一个基类,因此它们本质上完全不同,但它们都有一个同名的方法。 So, in FooHandler I'd like to have something like this: 所以,在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`.
}

So is there some neat trick I could use on an already instantiated object and still do that? 那么我可以在已经实例化的对象上使用一些巧妙的技巧并仍然这样做吗?

Is there a way to check if a class has a method 有没有办法检查一个类是否有方法

Class#getMethods() 类#的getMethods()

Returns an array containing Method objects reflecting all the public member methods of the class or interface represented by this Class object, including those declared by the class or interface and those inherited from superclasses and superinterfaces 返回一个包含Method对象的数组,这些对象反映此Class对象所表示的类或接口的所有public成员方法,包括由类或接口声明的那些以及从超类和超接口继承的那些

Class#getMethod(String,Class...) 类#getMethod(字符串,类...)

Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object. 返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定公共成员方法。 The name parameter is a String specifying the simple name of the desired method . name参数是一个String,指定the desired method的简单名称。

Throws: 抛出:

NoSuchMethodException - if a matching method is not found NoSuchMethodException - 如果找不到匹配的方法

Sample code: 示例代码:

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();
}

output: 输出:

close method is invoked

Yes you could use reflection for this, something like this would do it 是的,你可以使用反射,这样的事情就可以了

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;
}

The method to get the method object is Class#getMethod(String, Class...) , it allows you to find the specific method you are looking for using it's signature (the formal parameter list) so among all overloaded methods you get exactly the one you need. 获取方法对象的方法是Class#getMethod(String,Class ...) ,它允许您使用它的签名(形式参数列表)找到您正在寻找的特定方法,因此在所有重载方法中,您可以获得一个你需要的。

In all the exception thrown the one you might be the most interested in is InvocationTargetException which tells you that the method invoked has thrown an exception. 在抛出的所有异常中,您可能最感兴趣的是InvocationTargetException ,它告诉您调用的方法引发了异常。

You could do what others have already answered, but there are some ready-made options if you do not want to mess too much with reflection. 你可以做其他人已经回答过的事情,但是如果你不想用反思搞得太多,那么有一些现成的选择。 An example is Apache Commons BeanUtils : 一个例子是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
}
...

These libraries also tend to keep a method cache, so you get fast reflection; 这些库也倾向于保留方法缓存,因此您可以快速反映; by caching you skip the slow part of reflection: method lookup. 通过缓存,您可以跳过反射的缓慢部分:方法查找。

暂无
暂无

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

相关问题 有没有办法检查一个类是否具有main方法? - is there a way to check if a class has the main method? 有没有办法可以使用该类的现有实例(对象) - Is there a way i can use the existing instance (object) of the class 如何从Scala为现有Java类实例调用公共静态方法? - How to invoke public static method for existing Java class instance from Scala? 用Java检查类的天气对象是否分配了类实例的方法是什么? - What is way to check weather object of class is assigned an instance of class or not in Java? 调用类型为Class的对象的方法 - Invoke a method of an object of type Class 有没有办法使用名称为 class 的字符串调用 class 的 static 方法? - Is there a way to invoke a static method of a class using a string which has the name of the class? “对象不是声明类的实例”在 @Before Spring AOP 中使用 JoinPoint 调用 Method.invoke() - “object is not an instance of declaring class” at calling Method.invoke() with JoinPoint in @Before Spring AOP method.invoke-java.lang.RuntimeException:java.lang.IllegalArgumentException:对象不是声明类的实例 - method.invoke - java.lang.RuntimeException: java.lang.IllegalArgumentException: object is not an instance of declaring class 如果对象具有特定方法,是否有办法检查Java运行时? - Is there a way to check in Java runtime if an object has a specific method? 是否可以在现有对象中模拟单个方法? - Is it possible to mock a single method in an already existing object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM