1

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

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用匿名内部类覆盖,我无法访问任何被覆盖的成员,即使他们是上市。

4

2 回答 2

2

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

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

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

  • 它们不能是最终的,并且
  • 他们需要被分配到不重新声明。

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

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


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

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

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

于 2012-08-19T01:06:59.913 回答
-2

你没有这样的课程:

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

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

于 2012-08-18T23:48:52.543 回答