Android Studio上的Java Reflection无法找到要调用的公共静态方法

时间:2019-04-02 05:44:36

标签: java android api reflection

我的Android应用程序中的Java反射代码从包A调用包B中的公共静态方法。

最近,在对Gradle进行一些升级之后,我无法调用相同的方法。我的实现因NoSuchMethodFound异常而失败。如何获取实现才能找到此方法?

我尝试打印该类中所有可用的方法。结果是所有公共非静态方法。没有静态方法可用于调用。我要调用的方法是一个静态的“ getInstance”方法,该方法初始化该类并返回一个单例实例。

呼叫代码:

implementationClass = Class.forName(CLIENT_CLASS_NAME, false, ClientProvider.class.getClassLoader());
final Method method = implementationClass.getMethod("getInstance", (Class[]) null);
result = method.invoke(null, (Object[]) null);

被叫代码:

/**
* Public static method to be reflected.
*/
public static ClientImpl getInstance() {
    return ClientImplHolder.INSTANCE;
}

/**
 * Private class used to hold the lazily initialized singleton instance.
 */
private static class ClientImplHolder {
    private static final ClientImpl INSTANCE = new ClientImpl();
}

尝试“ getMethod”时,我收到一个NoSuchMethodException。

不知道我在这里做错了什么,感谢您的帮助。谢谢!

4 个答案:

答案 0 :(得分:0)

如果我理解正确,则您使用了错误的反射API

只需尝试一下。

public class Test {

    public static void main(String[] args) {
        try {
            ClientImpl client = (ClientImpl) Class.forName(ClientImpl.class.getCanonicalName())
                    .getMethod("getInstance")
                    .invoke(null);

            System.out.println(client.toString() + " with some -> " + client.getSome());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

/**
 * Public static method to be reflected.
 */

class ClientImpl {

    private final int some;

    public int getSome() {
        return some;
    }

    private ClientImpl(int some) {
        this.some = some;
    }

    public static ClientImpl getInstance() {
        return ClientImplHolder.INSTANCE;
    }

    /**
     * Private class used to hold the lazily initialized singleton instance.
     */
    private static class ClientImplHolder {
        private static final ClientImpl INSTANCE = new ClientImpl(123);
    }
}

它将正确放置结果

ClientImpl@<hashcode> with some -> 123

在反射API中使用静态方法时,无需显式调用ClassLoader,而必须将其canonicalName放在参数中,然后可以调用其方法。

答案 1 :(得分:0)

尝试替换它,也许是参数问题。

    final Method method = implementationClass.getMethod("getInstance");
    result = method.invoke(null);

答案 2 :(得分:0)

从Android 9(API级别28)开始,该平台限制了您的应用可以使用哪些非SDK接口。每当应用程序引用非SDK接口或尝试使用反射获取其句柄时,这些限制就会适用。

答案 3 :(得分:0)

结果证明,Proguard正在从构建中删除该方法,因为该方法未在其他地方使用。为课程添加了一个例外,问题就消失了。