簡體   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