【问题标题】:Why can't I access overridden public fields in an anonymous inner class?为什么我不能访问匿名内部类中被覆盖的公共字段?
【发布时间】:2023-03-28 17:34:01
【问题描述】:

我有一个无法更改的课程,如下所示:

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 返回一个普通的'ol Foo,这很好用,但如果我尝试用匿名内部类覆盖Foo,我即使他们是公开的,也无法访问任何被覆盖的成员。

【问题讨论】:

  • 你在做什么看起来“奇怪”,但我会从告诉你最终 int ID 的错误消息开始 - 你的匿名构造函数正试图再次设置一个 final。也许尝试使 ID 成为非最终的。
  • 你不能这样做,错误信息告诉你原因。

标签: java inner-classes scriptengine


【解决方案1】:

我认为这个问题有两个方面。

您的 Java 代码在语法上是有效的(我认为),但几乎可以肯定它不会按照您的意愿执行。具体来说,匿名类中的声明不会替换Foo 类中的声明。相反,匿名类的每个实例都会获得两组字段。 Foo 中声明的方法只会看到原始字段,匿名类中声明的任何方法都会看到新字段。

如果您希望匿名子类中的字段具有不同的值,那么:

  • 它们不能是最终的,并且
  • 需要将它们分配为未重新声明。

我无法真正建议解决此问题的最佳方法,但我认为您需要开始将 Foo 字段设为私有,并为它们提供 getter 和/或 setter。在设置器的情况下,您可以使用访问修饰符来允许匿名子类设置字段,但不能设置无关代码。

底线是您不能 覆盖 Java 中的字段。您的代码所做的不是覆盖,而是隐藏字段。


另一方面是被包装的异常来自 Javascript 引擎。我认为问题在于匿名类是隐式私有的,因此您的 Javascript sn-p 正试图访问私有类上的字段。当 Javascript 引擎尝试执行此操作时(我希望使用 Java 反射),它会收到运行时异常。

这里唯一不幸的是,异常消息没有说明为什么它无法访问该成员,但是您的 Java 代码足够“奇怪”,这并不让我感到惊讶。

作为一种解决方法,我建议将匿名类替换为非嵌套类。

【讨论】:

    【解决方案2】:

    你没有这样的课程:

    public class Foo {
        public final int ID=0;
        public int bar;
        public final Object baz;
    }
    

    因为那不会编译(不能声明 baz)。

    【讨论】:

    • 在没有初始化器的情况下声明 final 字段是合法的。它被称为空白决赛。要求是该字段在所有构造函数和实例初始化程序中只初始化一次。为了简洁起见,大概 OP 从示例中省略了这些。
    • 我并不是为了聪明才智。 OP 专门询问如何覆盖字段,其中一些是未分配的最终字段。由于这与问题绝对相关,因此他发布了“真实”代码很重要。我注意到他现在编辑了它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多