开发者社区> 问答> 正文

在Javassist中,使用CtMethod创建动态方法时如何将方法的返回类型设置为Double

我必须在运行时动态创建一个类和方法。我为此使用Javassist:

我要动态创建的方法是:

public Double formula1(FormulaAPI api) {  
      return api.evaluate(\"L\"); 
}

如果我将上述整个方法作为方法主体传递给CtMethod.make(..),则效果很好。

但是我想使其更通用,即我只想将其return api.evaluate("L"); 作为方法主体,并希望使用JavaAssist API方法来设置名称,返回类型等。当尝试这样做时,出现错误:

***Exception in thread "main" java.lang.VerifyError: 
    (class: Formulae, method: formula1 signature: (Lcom/formula/FormulaAPI;)D) Wrong return type in function***

我的问题是:调用时:CtMethod m = new CtMethod(...); 如何将CtMethod的返回类型设置为java.lang.Double而不是CtPrimitiveType.doubleType?

我的整个源代码是:

public class JavaAssistTest {
  private static final String className = "Formulae";
  private static final String methodName = "formula1";

  public static void main(String[] args) throws Exception{
      JavaAssistTest jj = new JavaAssistTest();
    try {
      Class clazz = jj.generateClass(className, methodName);

      Object obj = clazz.newInstance();
      Method method = clazz.getDeclaredMethod(methodName,FormulaAPI.class);
      FormulaAPI api = new FormulaAPI();
      method.invoke(obj,api);
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (CannotCompileException e) {
      e.printStackTrace();
    }
  }
  public Class generateClass(String className, String methodName)
      throws CannotCompileException, NotFoundException{
    ClassPool pool = ClassPool.getDefault();
    CtClass cc = pool.makeClass(className);

    ClassLoader classLoader = FormulaAPI.class.getClassLoader();
    pool.appendClassPath(new LoaderClassPath(classLoader));
    pool.importPackage("com.formula");

    String methodBody = "return $1.evaluate(\"L\");";

    CtClass apiClass = pool.get("com.formula.FormulaAPI");

    CtMethod m = new CtMethod(CtPrimitiveType.doubleType,methodName,new CtClass[]{apiClass},cc);
    m.setBody(methodBody);
    cc.addMethod(m);

    return cc.toClass();
  }

}

FormulaAPI类如下:

public class FormulaAPI {
    public Double evaluate(String source){
        System.out.println("printing in FormulaAPI ");
        return 2.0;
    }
}

问题来源:Stack Overflow

展开
收起
montos 2020-03-24 14:16:33 2588 0
1 条回答
写回答
取消 提交回答
  • 显然,CtPrimitiveType.doubleType不是使用CtClass类型,因为您需要包装类,这就是为什么您要获取异常。

    但是解决方案非常简单,您只需要将Double类型作为CtClass并使用它即可。因此,将您的generate方法修改为如下所示:

    public Class generateClass(String className, String methodName)
                throws CannotCompileException, NotFoundException {
       ClassPool pool = ClassPool.getDefault();
       CtClass cc = pool.makeClass(className);
    
       ClassLoader classLoader = FormulaAPI.class.getClassLoader();
       pool.appendClassPath(new LoaderClassPath(classLoader));
       pool.importPackage("com.formula");
    
       String methodBody = "return $1.evaluate(\"L\");";
    
       CtClass apiClass = pool.get("com.formula.FormulaAPI");
    
       CtClass doubleWrapperClass = pool.get("java.lang.Double");
    
       CtMethod m = new CtMethod(doubleWrapperClass,methodName,new CtClass[]{apiClass},cc);
       m.setBody(methodBody);
       cc.addMethod(m);
    
       return cc.toClass();
    }
    

    通过这些修改运行代码,您应该没有例外。

    回答来源:Stack Overflow

    2020-03-24 14:17:02
    赞同 展开评论 打赏
问答分类:
API
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
建立联系方法之一 立即下载
低代码开发师(初级)实战教程 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载