7

我有以下问题:我有一个类,试图使用反射来调用其 OWN 受保护的方法之一,但出现异常:java.lang.IllegalAccessException: access to method denied

有人可以对此有所了解吗?

基类:

public abstract class BaseReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // invoke the correct event method:
        Method method;
        try {
            method = this.getClass().getDeclaredMethod("testMethod");
            method.invoke(this);
        } catch (Throwable ex) {
             // ... display exception message
        }
    }

    protected void testMethod() {
    }

}

派生的具体类:

class MyReceiver extends BaseReceiver {
    @Override
    protected void testMethod() {
        // display error message
    }
}
4

2 回答 2

17

受保护的方法只能从包、类本身或扩展它的类中访问。

据我所知(基于Exception)您的扩展类(MyReceiver)在另一个包中,然后是超类(BaseReceiver)。意义:

  1. MyReceiver并且BaseReceiver不在同一个包中;
  2. BaseReceiver不扩展MyReceiver

现在,正如您在代码中看到的那样,您正在做:method = this.getClass().getDeclaredMethod("testMethod");这看起来不错,但这不是您想要的。由于此方法将返回MyReceiver.testMethod()方法,并且无法从中访问BaseReceiver(如您所见,您正在使用this.getClass()返回实例类的方法,在这种情况下MyReceiver)。

你可以做一些事情:

...
method = BaseReceiver.class.getDeclaredMethod("testMethod");
...

有了这个,您指示您希望在BaseReceiver类上声明受保护的方法。当然,当您稍后调用它时,method.invoke(this);您将调用被覆盖的方法。

但是在这种情况下使用反射是没有意义的,因为你有testMethod()可用的,并且调用它(就像 this.testMethod() 一样简单)你将调用被覆盖的反射。

另一种可能性是setAccessible(true)使用以下方法:

method = getClass().getDeclaredMethod("testMethod");
method.setAccessible(true);
method.invoke(this);
于 2012-06-24T09:17:42.130 回答
1

thisin的静态类型BaseReceiverBaseReceiver,因此您通常无法访问MyReceiver.testMethod. 除此之外,反射 API 检查调用者类,而不是实例(考虑到反射的用途,这本身就是疯了)。

您应该可以使用BaseReceiver.testMethod.

在大多数(但不是全部)使用反射的情况下,反射是一个坏主意。

于 2012-06-24T14:24:18.503 回答