Ответ 1
Причина, по которой вы получаете это, заключается в том, что суперкласс имеет доступ к уровню пакета.
Если вы измените модификатор доступа класса A
на public
(вам нужно будет поместить его в свой собственный файл), дополнительный метод в B.class.getDeclaredMethods()
исчезнет.
(Также обратите внимание, что abstract
, измененный в классе A
, является красной селедкой: то же самое происходит, когда класс A
не абстрактный)
Обходной путь в компиляторе Java для ошибки в отражении: хотя foo
является общедоступным методом, он был определен в классе с областью охвата A
. Вы можете подумать о классе B
, найти метод, попытаться вызвать его с помощью отражения, только чтобы получить IllegalAccessException
.
Компилятор будет генерировать метод bridge в классе B
, чтобы вы могли правильно отражать метод foo
.
Это лучше всего продемонстрировать, если вы сделаете метод foo
в методе A
a final
, что делает невозможным исправить эту ошибку отражения (невозможно переопределить метод)
Классы A
и B
находятся в пакете abc
, а класс C
- в пакете def
. Класс C
пытается рефлексивно вызывать метод foo
в классе B
, который является общедоступным, но он терпит неудачу, потому что он был определен в непубличном классе A
.
Исключение в потоке "main" java.lang.IllegalAccessException: Class def.C не может получить доступ к члену класса abc.A с модификаторами "public Окончательный"
package abc;
public class B extends A {
}
class A {
public final void foo() {
}
}
package def;
import java.lang.reflect.Method;
import abc.B;
public class C {
public static void main(String[] args) throws Exception {
Method m = B.class.getMethod("foo");
m.invoke(new B());
}
}
Просто удаление ключевого слова final
из метода foo
устраняет проблему, потому что компилятор затем вставляет метод синтетического моста в класс B
.
В этом сообщении об ошибке объясняется:
http://bugs.java.com/view_bug.do?bug_id=6342411
Описание
Нижеприведенная программа не работает во время выполнения с этой ошибкой:
Exception in thread "main" java.lang.IllegalAccessException: Class refl.ClientTest can not access a member of class refl.a.Base with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65) at java.lang.reflect.Method.invoke(Method.java:578) at refl.ClientTest.main(ClientTest.java:9)
========== test/refl/a/Base.java ========== 1 package refl.a; 2 3 class Base { 4 public void f() { 5 System.out.println("Hello, world!"); 6 } 7 } ========== test/refl/a/Pub.java ========== 1 package refl.a; 2 3 public class Pub extends Base {} ========== test/refl/ClientTest.java ========== 1 package refl; 2 import refl.a.*; 3 import java.lang.reflect.*; 4 5 public class ClientTest { 6 public static void main(String[] args) throws Exception { 7 Pub p = new Pub(); 8 Method m = Pub.class.getMethod("f"); 9 m.invoke(p); 10 } 11 }
ОЦЕНКА
Предложение состоит в том, чтобы добавить мостовые методы в этих очень редких случаях, чтобы исправить проблема в размышлении без каких-либо других предварительных исправлений или обходных решений. В частности, мы будем генерировать метод моста, когда публичный метод наследуется от непубличного класса в открытый класс.