0

현재 자바 코드를 문자열 형식으로 실행하는 방법을 연구 중입니다. 그래서 여기에 내가 어떻게 그랬어.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); 
} 

다음과 같은 경우 문제가 발생합니다. 그것이 실패하고이 오류 메시지가이 코드를 작동 //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) 

을 수단 - 어떤 이유

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); 
} 

는 이해가 안 돼요. 그러나 그것을 다루는 더 좋은 방법을 제안하십시오. 또한 클래스를 파싱하는 동안 오류를주지 않는 이유는 무엇입니까? 그리고 내가 기대할 수있는 다른 놀라움은 무엇입니까?

답변

2

Java와 Groovy의 차이점을 발견했습니다.

Java에서는 문장이 세미콜론으로 끝납니다.

Groovy에서는 문장이 이미 완전한 문장 인 경우 줄 바꿈으로 세미 음울로 완성됩니다 (또는). 귀하의 경우에는

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

이 두 문장 인 코드를 의미한다.

첫 번째 문언은 double calculatedAnswer = (Double)입니다.

Groovy에서 을 생략해도 클래스를 참조 할 수 없기 때문에 Double.classDouble으로 작성 될 수 있습니다.

그렇다면 Double 클래스 개체를 double 변수에 할당한다는 것입니다. 괄호는 단지 no-op입니다.

Double 클래스 개체는 double에 자동으로 대문자로 쓰일 수 없으므로 물론 메시지가 말하는 것처럼 실패합니다.

당신은 명시 적으로이 예상처럼 작동 것이다에

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

같은 문을 끝나지 만들기 위해 LINEBREAK을 피할 수 있습니다.

물론 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 –

관련 문제