3

rhino で javascript から Java メソッドをオーバーライドする方法を探しています。これが私のコードです:

public class CustomClass {
public String s="some string";
public void doSomething(){}
}

その後:

        Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
        ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);
        String s="CustomClass.s='aaa'; \n CustomClass.doSomething=function(args){};";
        Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

そのため、値を CustomClass.s に変更することはできますが、メソッド doSomething には変更できません。

次のエラーが表示されます。

org.mozilla.javascript.EvaluatorException: Java メソッド "doSomething" を割り当てることができません。(#2)

UPDATE コメントで要求されたように、ここに私の完全なソースコードがあります:

CustomClass.java

public class CustomClass {
    public String s="Do something now!";

    public void doSomething(Object ... v){
        System.out.println("do something");
    }
}

Scripting.java

import org.mozilla.javascript.*;
public class Scripting {
    public static void main(String args[])
    {

        Context cx = Context.enter();
        try {

            Scriptable scope = cx.initStandardObjects();

            Object wrappedOut = Context.javaToJS(new CustomClass(), scope);
            ScriptableObject.putProperty(scope, "CustomClass", wrappedOut);


            String s="CustomClass.doSomething=function(args){};";

            Object result = cx.evaluateString(scope, s, "<cmd>", 1, null);

            System.err.println(Context.toString(result));
        }catch(WrappedException e){
            e.printStackTrace();

        } catch(Exception e){
            e.printStackTrace();
        }finally {
            // Exit from the context.
            Context.exit();
        }
    }
}
4

1 に答える 1

1

このコードを実行すると、Rhino は JavadoSomethingメソッドを呼び出しません。代わりに、対応する JavaScript (欠落している)を呼び出そうとし、例外をスローし sun.org.mozilla.javascript.internal.EvaluatorException: Java class "CustomClass" has no public instance field or method named "doSomething". (#1)ます。

あなたCustomClassのクラスは純粋な Java クラスであり、対応する JavaScript はありません。ソースの次の行を置き換えると:

String s="CustomClass.doSomething=function(args){};";

この行で:

String s = "CustomClass";

javasript コマンドとして評価すると、 として出力されCustomClass@15e0be38ます。これは通常、 class のオブジェクトの some("15e0be38") インスタンスであることを意味しますCustomClass

メソッドの apidoc からScriptableObject.defineClass(Scriptable scope, java.lang.Class clazz):


Scriptable を実装する Java クラスから JavaScript オブジェクトを定義します。
(...)
次に、すべてのメソッドがスキャンされ、JavaScript オブジェクトを定義するための特別な意味を持つことを示す特別なプレフィックスが検出されます。これらの特別なプレフィックスは

JavaScript 関数の場合
は jsFunction_ コンストラクターのプロパティである JavaScript 関数の場合はjsStaticFunction_ jsGet_
JavaScript プロパティのゲッターの場合
jsSet_ JavaScript プロパティのセッターの場合
jsConstructor コンストラクターである JavaScript 関数の場合

メソッドの名前が「jsFunction_」で始まる場合、JavaScript 関数は、「jsFunction_」に続く Java メソッド名の残りの部分から形成された名前で作成されます。したがって、「jsFunction_foo」という名前の Java メソッドは、JavaScript メソッド「foo」を定義します。この JavaScript 関数を呼び出すと、Java メソッドが呼び出されます。メソッドのパラメーターは、FunctionObject クラスで定義されている数と型である必要があります。次に、JavaScript 関数がプロトタイプのプロパティとして追加されます。


JavaScriptprintメソッド ((org.mozilla.javascript.tools.shell.Globalクラスで定義)) は、JavaSystem.out.printlnメソッドへのインターフェイスです。実行時

public class CustomClass {

public static class _CustomClass extends ScriptableObject {

    @Override
    public String getClassName() {
        return "CustomClass";
    }

    public int jsFunction_method() {
        System.out.println("from java method");
        return 2;
    }
}

public static void main(String[] args) {
    Context context = Context.enter();
    Global global = new Global(context);
    try {            
        //ScriptableObject.defineClass(global, CustomClass.class); 
        ScriptableObject.defineClass(global, _CustomClass.class);            
        String script = "myInstance = new CustomClass();myInstance+' ';";
        System.out.println(context.evaluateString(global, script, "", 1, null));
        script = "myInstance.method+' '+myInstance.method()";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
        script = "CustomClass.prototype.method=function(){print('overriden from javascript method');return 3;}";
        context.evaluateString(global, script, "", 1, null);
        script = "myInstance.method+' '+myInstance.method();";
        System.out.println(context.evaluateString(global, script, "script", 1, null));
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        Context.exit();
    }
  }
  }

それは出力します:

[object CustomClass]
from java method
function method() {
[native code, arity=0]
}
 2

overriden from javascript method
function () {
    print("overriden from javascript method");
    return 3;
}
 3
  • この同じ JS コードが Chrome で実行された場合、別の方法で実行されることに注意してください - 2 を 2 回返します。
  • (コメントのように)外部クラスが使用されていた場合、一般的な関連するコンパイル時エラーが発生していたでしょう。このコードはRhino 1.7r2を使用して作成されました。
于 2013-01-07T23:30:52.083 に答える