3

I am trying to figure out how to use a loop to build a JExpression that I can use in an .assign() call. I know that you can do something like JExpr.invoke("methodA").invoke("methodB") with JCodeModel, but I want to be able to add each .invoke() method based on a list of method names. Does anyone know how to do this?

Example of my Generator code [this is assuming that I have modified the ArrayList.add() method to return the ArrayList]:

JDefinedClass newClass = jCodeModel._class("com.me.GeneratedClass");
JClass refObject = jCodeModel.ref(Object.class);
JClass refArrayList = jCodeModel.ref(ArrayList.class);

JFieldVar objectList = newClass.field(refArrayList, "objects");

JBlock methodBody = newClass.method(JMod.PUBLIC, refArrayList, "getNewObjectList");

String[] methodsToInvoke = {"add", "add", "add"};

JExpression rhsAssignmentExpression = JExpr._new(refArrayList).narrow(refObject);
for(String methodName : methodsToInvoke) {
    rhsAssignmentExpression.invoke(methodName).arg(JExpr._new(refObject));
}

methodBody.assign(objectList, rhsAssignmentExpression);
methodBody._return(objectList);

Example of what I am trying to generate:

class GeneratedClass {

   ArrayList<Object> objects;

   public ArrayList<Object> getNewObjectList()
   {
      objects = new ArrayList<Object>().add(new Object()).add(new Object()).add(new Object());
      return objects;
   }
}

My problem is that this method doesn't chain the invoke methods, but replaces them so the generated code looks like this:

class GeneratedClass {

   ArrayList<Object> objects;

   public ArrayList<Object> getNewObjectList()
   {
      objects = new ArrayList<Object>().add(new Object());
      return objects;
   }
}
4

2 回答 2

1

这也可以通过让 JCodeModel 打印原始字符串而不是声明 JCode 对象来完成。对于这个特定的问题,不需要生成 java-imports——因此可以使用 directStatement() 来完成。

StringBuilder expression = new StringBuilder();
expression.append (“objects = new ArrayList<Object>()”);

if ((methodsToInvoke != null) && (methodsToInvoke.length > 0))
{
   for(String methodName : methodsToInvoke)
   {
      expression.append(“.add(new Object())”);
   }
}

expression.append(“;”);

methodBoby.directStatement(expression.toString());
于 2014-03-20T18:42:04.783 回答
0

您需要做的是为每个 invoke() JExpression 调用存储一个中间值:

JExpression rhsAssignmentExpression = JExpr._new(refArrayList);
for(String methodName : methodsToInvoke) {
    rhsAssignmentExpression = rhsAssignmentExpression.invoke(methodName).arg(JExpr._new(refObject));
}

这避免了每次重新定义调用,并有效地链接调用。结果如下:

public class GeneratedClass {

    public ArrayList objects;

    public ArrayList getNewObjectList() {
        objects = new ArrayList().add(new Object()).add(new Object()).add(new Object());
        return objects;
    }

}
于 2014-03-21T01:38:22.113 回答