Почему я не могу получить доступ к переопределенным публичным полям в анонимном внутреннем классе?
У меня есть класс, который я не могу изменить следующим образом:
public class Foo {
public final int ID=0;
public int bar;
public final Object baz=null;
}
Я хочу иметь анонимный внутренний класс, который переопределяет Foo
такие как:
public Foo newFoo(final int mID, final int mbar, final Object mbaz) {
return new Foo(){
public final int ID = mID;
public int bar = mbar;
public final Object baz = mbaz;
};
}
Тогда у меня есть javax.script.ScriptEngine
что я хочу назвать что-то вроде этого в JS: newFoo(0,0,undefined)["ID"]
Моя проблема в том, что я получаю исключение, подобное этому:
sun.org.mozilla.javascript.internal.WrappedException: Wrapped java.lang.IllegalAccessException: Class sun.org.mozilla.javascript.internal.JavaMembers can not access a member of class Baz$1 with modifiers "public final" (mod.js#9) in test.js at line number 9
Я не понимаю, как я мог получить здесь проблему: это прекрасно работает, если newFoo
возвращает простой Foo
, но если я попытаюсь переопределить Foo
с анонимным внутренним классом я не могу получить доступ к переопределенным членам, даже если они общедоступны.
2 ответа
Я думаю, что есть две стороны этой проблемы.
Ваш Java-код синтаксически допустим (я думаю), но он почти наверняка не делает то, что вы от него хотите. В частности, объявления в анонимном классе не заменяют объявлений в Foo
учебный класс. Вместо этого каждый экземпляр анонимного класса получает два набора полей. Методы, объявленные в Foo
будут видеть только исходные поля, а любые методы, объявленные в анонимном классе, будут видеть новые поля.
Если вы хотите иметь разные значения для полей в анонимном подклассе, то:
- они не могут быть окончательными, и
- они должны быть назначены, а не повторно объявлены.
Я не могу посоветовать лучший способ решить эту проблему, но я думаю, вам нужно начать с Foo
частные поля и предоставление для них геттеров и / или сеттеров. В случае с установщиками вы можете использовать модификаторы доступа, чтобы позволить анонимному подклассу устанавливать поле, но не связанный код.
Суть в том, что вы не можете переопределить поля в Java. То, что делает ваш код, не переопределяет, а скрывает поля.
Другой аспект заключается в том, что исключение, заключенное в оболочку, исходит от движка Javascript. Я думаю, что проблема в том, что анонимные классы неявно являются закрытыми, и поэтому ваш фрагмент Javascript пытается получить доступ к полю частного класса. Когда движок Javascript пытается это сделать (я полагаю, с помощью отражения Java), он получает исключение во время выполнения.
Единственная неприятная вещь здесь - это то, что сообщение об исключении не говорит, почему оно не может получить доступ к члену, но ваш Java-код достаточно "странный", что меня это не удивляет.
В качестве обходного пути я бы предложил заменить анонимный класс не вложенным классом.
У вас нет такого класса:
public class Foo {
public final int ID=0;
public int bar;
public final Object baz;
}
Потому что это не скомпилируется (baz не может быть объявлен).