Почему я не могу получить доступ к переопределенным публичным полям в анонимном внутреннем классе?

У меня есть класс, который я не могу изменить следующим образом:

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 не может быть объявлен).

Другие вопросы по тегам