2017-12-07 17 views
0

現在、私は文字列形式でJavaコードを実行する方法を研究しています。だからここで私はそれをやった。Groovyスクリプトエンジン(GroovyClassLoader)で新しい行 " n"を含むjavaコードを実行しているときにGroovyCastExceptionが発生しました

import java.util.HashMap; 
import java.util.Map; 

import groovy.lang.GroovyClassLoader; 

public class GroovyStackOverflow { 

    public static void main(String[] args) { 
     GroovyClassLoader gcl = new GroovyClassLoader(); 
     String codeSnippet = "double calculatedAnswer = (Double)" 
       + "contextMap.get(\"doubleValue\") * (Double)contextMap.get(\"doubleValue\");" 
       + " calculatedAnswer = Math.sqrt(calculatedAnswer); " 
       + "calculatedAnswer = calculatedAnswer * calculatedAnswer;" 
       + "System.out.println(calculatedAnswer);" 
       + " return calculatedAnswer;"; 
     StringBuilder sb = new StringBuilder(); 
     sb.append("public class ScriptImplementor implements ScriptEvaluator { public Object evaluate(Map contextMap) {"); 
     sb.append(codeSnippet); 
     sb.append("} }"); 
     Class<?> clazz = gcl.parseClass(sb.toString()); 
     ScriptEvaluator scriptEvaluator = null;  
     double calculatedAnswer = 100.0;   
     try { 
      Map contextMap = new HashMap(); 
      contextMap.put("doubleValue", (double)100.0); 
      contextMap.put("threadId", "thread"+100); 
      contextMap.put("hashCode", 100); 
      scriptEvaluator = (ScriptEvaluator) clazz.newInstance(); 
      scriptEvaluator.evaluate(contextMap);; 
     } catch (InstantiationException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

public interface ScriptEvaluator { 
    public Object evaluate(Map contextMap); 
} 

問題は次の場合に問題になります。

import java.util.HashMap; 
import java.util.Map; 

import groovy.lang.GroovyClassLoader; 

public class GroovyStackOverflow { 

    public static void main(String[] args) { 
     GroovyClassLoader gcl = new GroovyClassLoader(); 
     String codeSnippet = "double calculatedAnswer = (Double)" 
       + "\n " 
       + "contextMap.get(\"doubleValue\") * (Double)contextMap.get(\"doubleValue\");" 
       + " calculatedAnswer = Math.sqrt(calculatedAnswer); " 
       + "calculatedAnswer = calculatedAnswer * calculatedAnswer;" 
       + "System.out.println(calculatedAnswer);" 
       + " return calculatedAnswer;"; 
     StringBuilder sb = new StringBuilder(); 
     sb.append("public class ScriptImplementor implements ScriptEvaluator { public Object evaluate(Map contextMap) {"); 
     //sb.append(codeSnippet.replaceAll("\n", " ")); 
     sb.append(codeSnippet); 
     sb.append("} }"); 
     Class<?> clazz = gcl.parseClass(sb.toString()); 
     ScriptEvaluator scriptEvaluator = null;  
     double calculatedAnswer = 100.0; 
     try { 
      Map contextMap = new HashMap(); 
      contextMap.put("doubleValue", (double)100.0); 
      contextMap.put("threadId", "thread"+100); 
      contextMap.put("hashCode", 100); 
      scriptEvaluator = (ScriptEvaluator) clazz.newInstance(); 
      scriptEvaluator.evaluate(contextMap);; 
     } catch (InstantiationException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
public interface ScriptEvaluator { 
    public Object evaluate(Map contextMap); 
} 

それが失敗し、このエラーメッセージは、このコード//sb.append(codeSnippet.replaceAll("\n", " "));をコメント解除した後

Exception in thread "main" org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class java.lang.Double' with class 'java.lang.Class' to class 'double' 
    at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToNumber(DefaultTypeTransformation.java:163) 
    at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.doubleUnbox(DefaultTypeTransformation.java:88) 
    at ScriptImplementor.evaluate(script15126616543572010791987.groovy:1) 
    at GroovyStackOverflow.main(GroovyStackOverflow.java:33) 

をmeans-何それが動作する理由私は理解していません。しかし、それを処理するより良い方法を提案してください。また、なぜそれはクラスを解析中にエラーを与えていないのですか? また、このように私が期待できる他の驚きは何ですか?

答えて

2

JavaとGroovyの違いがあります。

Javaでは、ステートメントはセミコロンで終了します。

Groovyでは、文がすでに完全な文である場合、サテライトはセミコロン(または)で改行で終了します。あなたのケースでは

これはコード

double calculatedAnswer = (Double) 
contextMap.get("doubleValue") * (Double)contextMap.get("doubleValue") 

は二つの文であることを意味します。

最初の文はdouble calculatedAnswer = (Double)です。

Groovyでは、.classを省略してクラスを参照できるため、Double.classDoubleと書くことができます。

したがって、Doubleクラスオブジェクトをdouble変数に割り当てます。カッコはここではno-opsです。

Doubleクラスオブジェクトは自動的にdoubleに大文字と小文字を区別することができないため、このメッセージは言うまでもなく失敗します。

あなたは明示的にそれは

あなたが期待されるように働くだろう
double calculatedAnswer = (Double)\ 
contextMap.get("doubleValue") * (Double)contextMap.get("doubleValue") 

のように文を終了しないようにする改行をエスケープすることができます。

もちろん、GroovyとJavaが異なる場合もあります。

Groovyの構文はJavaの構文に近いが、ではなく、と同じであることを常に覚えておいてください。

Afairそれぞれの有効なJavaコードも有効なGroovyコードですが、この例ではまったく同じ意味ではありません。

+0

私のコードで何が間違っているかを理解するのは本当に助かりました。また、JavaとGroovyのコードの違いを入力した結果、このリストが見つかりました.- https://stackoverflow.com/questions/687601/valid-java-code-that-is-not-valid-groovy-code/740641 –

関連する問題