Javaの「評価」メソッドを使用してGroovyスクリプトで定義された関数を使用する方法

ディディエ:

私はJavaからのGroovy呼び出しを発見し、このケースに問題があります:

グルーヴィーなファイルがあります: " test.groovy"

a = 1.0
def mul2( x ) { 2.0 * x }

そして、私はこのようなJavaコードからそれを使いたいです

GroovyShell gs = new GroovyShell();
gs.parse( new File( ".../test.groovy" ) ).run();

System.out.printf( "a = %s%n", gs.evaluate("a") ); // ok
System.out.printf( "mul2(a) = %s%n", gs.evaluate( "mul2(a)" ) ); // error

エラーは:

groovy.lang.MissingMethodException: No signature of method: Script1.mul2() is applicable for argument types: (BigDecimal) values: [1.0]

evaluate()メソッドを使用して、groovyスクリプトで定義された関数にアクセスするにはどうすればよいですか?

最終的にのようなものを評価したいので、「評価」メソッドを使用する必要がありますMath.sin( a * mul2(Math.Pi) )


今私は4つの解決策を持っています(4つ目は私が探したものです):

  1. 「Szymon Stepniak」の回答のように閉鎖を使用します
  2. 「daggett」の回答のように静的インポートを使用します
  3. 式を評価するスクリプトを使用して、Java関数を含むスクリプトを拡張します。

...クラス(JavaではGroovyではない)...

  public static abstract class ScriptClass extends Script
  {
    double mul2( double x )
    {
      return x * 2;
    }
  }

...コード...

  CompilerConfiguration config = new CompilerConfiguration();
  config.setScriptBaseClass(ScriptClass.class.getName());

  GroovyShell gs = new GroovyShell(config);

  System.out.printf( "result = %s%n", gs.evaluate("mul2(5.05)") );

それは機能しますが、コードはJavaであり、私が望むものではありませんが、それを行う必要がある人のためにここで注意します

  1. そして最後にgroovyスクリプトを拡張します:

groovyファイル:

double mul2( x ) { x * 2 } 
a=mul2(3.33)

それを使用するJavaコード

GroovyClassLoader gcl = new GroovyClassLoader();
Class<?> r = gcl.parseClass( resourceToFile("/testx.groovy") );
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass(r.getName());
GroovyShell gs = new GroovyShell(gcl, config);    

System.out.printf( "mul2(5.05) = %s%n", gs.evaluate("mul2(5.05)") );

// WARNING : call super.run() in evaluate expression to have access to variables defined in script
System.out.printf( "result = %s%n", gs.evaluate("super.run(); mul2(a) / 123.0") );

それはまさに私が欲しかったものです:-)

Szymon Stepniak:

ここで何が起こっているのかを理解するには、説明する価値のあることが2つあります。指定したスクリプトには2つの異なるスコープがあります。

変数aGroovyShellバインディングオブジェクトに格納されるため、すべてのgs.evaluate()呼び出しで使用できます。この例を見てください:

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;

final class ExecuteGroovyScriptExample {

    public static void main(String[] args) {
        final String script = "a = 1.0 \n" +
                "def mul2(x) { 2.0 * x }\n";

        final Binding binding = new Binding();

        final GroovyShell gs = new GroovyShell(binding);
        final Script sc = gs.parse(script);
        sc.run();

        System.out.printf("binding.getVariable(\"a\") == %s\n", binding.getVariable("a"));
    }
}

この例を実行すると、次の出力が生成されます。

binding.getVariable("a") == 1.0

2つ目は、すべてのgs.evaluate()呼び出しgroovy.lang.Scriptが、まったく異なるコンテキストを持つ新しいクラスを生成することですこれが以下を呼び出す理由です:

gs.evaluate("mul2(a)")

このようなものを投げます:

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: Script2.mul2() is applicable for argument types: (BigDecimal) values: [1.0]

gs.evaluate("mul2(a)")呼び出しから生成されるスクリプトクラスにmul2(x)メソッドが含まれていないためです。この呼び出しによって生成されるクラスは、次のようになります。

class Script2 extends groovy.lang.Script {
    void run() {
        mul2(a)
    }
}

ただし、gs.parse(script)contains mul2(x)メソッドから返されるスクリプトクラスなので、呼び出すことはできますが、呼び出しとしてでgs.evaluate()なく、呼び出すことができますScript.invokeMethod(name, args)このようなもの:

import groovy.lang.GroovyShell;
import groovy.lang.Script;

final class ExecuteGroovyScriptExample {

    public static void main(String[] args) {
        final String script = "a = 1.0 \n" +
                "def mul2(x) { 2.0 * x }\n";

        final GroovyShell gs = new GroovyShell();
        final Script sc = gs.parse(script);
        sc.run();

        System.out.printf("mul2(a) = %s%n", sc.invokeMethod("mul2", gs.evaluate("a")));
    }
}

この例では、次の出力が生成されます。

mul2(a) = 2.00

mul2(x)メソッドが呼び出された方法を見てくださいまず、によって返されgs.parse(script)スクリプトsc変数に格納し、次の呼び出しによってこのスクリプトで定義されたメソッドを呼び出すことができるようにします。

sc.invokeMethod("mul2", gs.evaluate("a"));

この例ではaによって変数の値を取得してgs.evaluate("a")いますがbinding、最初の例のオブジェクトを使用することもできます。また、a変数が次のように定義されている場合は注意してください。

def a = 1.0

または

@groovy.transform.Field
def a = 1.0

bindingオブジェクトには保存されなくなり、最初のケースではスクリプトのローカル変数aを定義し、2番目のケースではスクリプトクラスフィールドを定義しますa


または、次の呼び出しを実行する場合:

gs.evaluate("mul2(a)")

あるいは

gs.evaluate("Math.sin( a * mul2(Math.PI))")

入力Groovyスクリプトファイルを変更mul2(x)し、関数定義をa変数と同じスコープ内のクロージャーに置き換える必要があるため、bindingオブジェクトに格納されます。

a = 1.0
mul2 = { x -> 2.0 * x }

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

jsr223サンプルgroovyスクリプトのメソッド内で使用されるメソッド外で定義された変数を作成する方法

分類Dev

指定されたパラメータを使用してGroovyでメソッド(関数)を作成する方法(定義されていない)

分類Dev

メソッドにパラメーターとして渡されたクラスタイプを使用してローカル変数を定義する方法

分類Dev

Python / Djangoの「エクスポート」関数で以前に定義されたメソッド(funcs)を使用するにはどうすればよいですか?

分類Dev

クラスがそのメンバーを繰り返し評価するためにメソッドで使用するクラスメンバーの引数として関数を渡す方法は?

分類Dev

モジュールで明示的に定義されたメソッド/関数のリストを取得します

分類Dev

JavaScript:ファクトリ関数内の内部プロトタイプメソッドを使用して配列から評価値を返す

分類Dev

エンティティクラス内のメソッド定義を使用したクエリでのクエリクライアント評価エラーを回避する

分類Dev

デリゲートを使用して、プログラムクラスに見つからない別のクラスで定義されたメソッド

分類Dev

メソッドを使用して派生リストを定義し、C#でそれらを入力する方法

分類Dev

さまざまな引数を使用してS3メソッドを定義するためのベストプラクティス

分類Dev

クラスメソッドを外部で定義された関数として設定します

分類Dev

リストに格納された変数を使用してJavaでブール式を評価する

分類Dev

split、if、listを使用して、定義されたパラメーターのリストをチェックし、できればループする未定義の変数を使用してループを作成する際の問題

分類Dev

composer.jsonで定義されたComposerスクリプトを使用して、phpunitの色を表示する方法は?

分類Dev

ColabでPython変数を使用してスクリプトを実行するための更新されたメソッドはありますか?

分類Dev

Axiomを使用して作成されたDOMドキュメントを渡してPsychopathプロセッサでXPathを評価する方法

分類Dev

サブクラスでのみ定義されているメソッドを使用する-JAVA

分類Dev

C#でリフレクションを使用してメソッドから呼び出されたメソッドのリストを取得する方法

分類Dev

複数の関数/メソッドで使用されるクラスに変数を設定します

分類Dev

スクリプトの後半で定義されたカスタム関数でValidateScriptを使用する

分類Dev

oracleは(sql / plusを介して)SQLスクリプトの評価に使用される文字セットをどのように決定しますか

分類Dev

PHPでSoapCall関数を使用してSOAPリクエストを行った後、例外「メソッドが許可されていません」を取得する

分類Dev

Javaのブループリントで定義されたデータソースを使用してOracleデータベースにアクセスする

分類Dev

C#の他のクラスで定義されたメソッドを使用して、オブジェクトをバイト配列に変換します

分類Dev

モックされたメソッド引数を使用して次のステップをモックする

分類Dev

メソッドがクラスc ++で定義されていない場合に、クラスオブジェクトでメソッドを使用する方法

分類Dev

Luaのスクリプトで定義されている関数を使用せずに関数を実行する方法

分類Dev

1つのメインメソッドのみを使用したXUnitテストプロジェクト:「プログラムには複数のエントリポイントが定義されています。」

Related 関連記事

  1. 1

    jsr223サンプルgroovyスクリプトのメソッド内で使用されるメソッド外で定義された変数を作成する方法

  2. 2

    指定されたパラメータを使用してGroovyでメソッド(関数)を作成する方法(定義されていない)

  3. 3

    メソッドにパラメーターとして渡されたクラスタイプを使用してローカル変数を定義する方法

  4. 4

    Python / Djangoの「エクスポート」関数で以前に定義されたメソッド(funcs)を使用するにはどうすればよいですか?

  5. 5

    クラスがそのメンバーを繰り返し評価するためにメソッドで使用するクラスメンバーの引数として関数を渡す方法は?

  6. 6

    モジュールで明示的に定義されたメソッド/関数のリストを取得します

  7. 7

    JavaScript:ファクトリ関数内の内部プロトタイプメソッドを使用して配列から評価値を返す

  8. 8

    エンティティクラス内のメソッド定義を使用したクエリでのクエリクライアント評価エラーを回避する

  9. 9

    デリゲートを使用して、プログラムクラスに見つからない別のクラスで定義されたメソッド

  10. 10

    メソッドを使用して派生リストを定義し、C#でそれらを入力する方法

  11. 11

    さまざまな引数を使用してS3メソッドを定義するためのベストプラクティス

  12. 12

    クラスメソッドを外部で定義された関数として設定します

  13. 13

    リストに格納された変数を使用してJavaでブール式を評価する

  14. 14

    split、if、listを使用して、定義されたパラメーターのリストをチェックし、できればループする未定義の変数を使用してループを作成する際の問題

  15. 15

    composer.jsonで定義されたComposerスクリプトを使用して、phpunitの色を表示する方法は?

  16. 16

    ColabでPython変数を使用してスクリプトを実行するための更新されたメソッドはありますか?

  17. 17

    Axiomを使用して作成されたDOMドキュメントを渡してPsychopathプロセッサでXPathを評価する方法

  18. 18

    サブクラスでのみ定義されているメソッドを使用する-JAVA

  19. 19

    C#でリフレクションを使用してメソッドから呼び出されたメソッドのリストを取得する方法

  20. 20

    複数の関数/メソッドで使用されるクラスに変数を設定します

  21. 21

    スクリプトの後半で定義されたカスタム関数でValidateScriptを使用する

  22. 22

    oracleは(sql / plusを介して)SQLスクリプトの評価に使用される文字セットをどのように決定しますか

  23. 23

    PHPでSoapCall関数を使用してSOAPリクエストを行った後、例外「メソッドが許可されていません」を取得する

  24. 24

    Javaのブループリントで定義されたデータソースを使用してOracleデータベースにアクセスする

  25. 25

    C#の他のクラスで定義されたメソッドを使用して、オブジェクトをバイト配列に変換します

  26. 26

    モックされたメソッド引数を使用して次のステップをモックする

  27. 27

    メソッドがクラスc ++で定義されていない場合に、クラスオブジェクトでメソッドを使用する方法

  28. 28

    Luaのスクリプトで定義されている関数を使用せずに関数を実行する方法

  29. 29

    1つのメインメソッドのみを使用したXUnitテストプロジェクト:「プログラムには複数のエントリポイントが定義されています。」

ホットタグ

アーカイブ