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

この問題には2つの側面があると思います。

あなたのJavaコードは構文的に有効ですが(私は思う)、それはあなたが望むことをほぼ確実に実行しません。具体的には、匿名クラスの宣言は、Fooクラスの宣言を置き換えません。代わりに、匿名クラスの各インスタンスは2セットのフィールドを取得します。で宣言されたメソッドFooは元のフィールドのみを表示し、匿名クラスで宣言されたメソッドはすべて新しいフィールドを表示します。

匿名サブクラスのフィールドに異なる値を設定する場合は、次のようにします。

  • それらは最終的なものにはなり得ず、
  • 再宣言されないように割り当てる必要があります。

これを解決する最善の方法を実際にアドバイスすることはできませんが、フィールドをプライベートにし、ゲッターやセッターを提供することから始める必要があると思います。Fooセッターの場合、アクセス修飾子を使用して、匿名サブクラスがフィールドを設定できるようにすることができますが、無関係のコードは設定できません。

肝心なのは、Javaではフィールドをオーバーライドできない ということです。コードが実行しているのはオーバーライドではなく、フィールドを非表示にしていることです。


もう1つの側面は、ラップされた例外が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 に答える