使用 JCodeModel 生成 toString() 方法
Use JCodeModel to generate toString() method
我正在尝试使用 com.sun.codemodel.JCodeModel
.
生成 Java 值对象
我已经成功地生成了 hashcode()
和 equals()
方法,但我正在为 toString()
;
而苦苦挣扎
我需要以下toString()
实施
return "ClassName [field1 = " + field1 + ", field2 = " + field2 ... ", fieldN = " + fieldN + "]";
如何创建包含 JExpr.lit(field1.name())
与 JExpr.ref(fieldVar.name())
连接的 JCodeModel
JExpression
?
我所做的就是生成一个类似于以下内容的字符串文字:-
return "ClassName [field1 = field1 + field2 = field2 ... fieldN = + fieldN + ]";
到目前为止,这是我的骨架方法:-
final Map<String, JFieldVar> fields = jclass.fields();
final JMethod toString = jclass.method(JMod.PUBLIC, String.class, "toString");
final Set<String> excludes = new HashSet<String>(Arrays.asList(ruleFactory.getGenerationConfig().getToStringExcludes()));
final JBlock body = toString.body();
for (JFieldVar fieldVar : fields.values()) {
if (excludes.contains(fieldVar.name()) || ((fieldVar.mods().getValue() & JMod.STATIC) == JMod.STATIC)) {
continue;
}
??????????????
}
body._return(?????????);
toString.annotate(Override.class);
这里的关键点可能是你可以使用JExpression#plus
方法将多个JExpression
对象与+
运算符组合起来。
这是一个示例,其中包含简单示例 class 的定义,以及一般生成 toString
方法的方法:
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.writer.SingleStreamCodeWriter;
public class CodeModelToStringTest
{
public static void main(String[] args) throws Exception
{
JCodeModel codeModel = new JCodeModel();
JDefinedClass definedClass = codeModel._class("com.example.Example");
definedClass.field(JMod.PUBLIC, String.class, "exampleString");
definedClass.field(JMod.PROTECTED, int.class, "exampleInt");
definedClass.field(JMod.PRIVATE, float.class, "exampleFloat");
definedClass.field(JMod.PRIVATE, String.class, "excludedString");
definedClass.field(JMod.STATIC, String.class, "staticString");
createToStringMethod(definedClass, Arrays.asList("excludedString"));
CodeWriter codeWriter = new SingleStreamCodeWriter(System.out);
codeModel.build(codeWriter);
}
private static void createToStringMethod(
JDefinedClass definedClass,
Collection<String> excludedFieldNames)
{
Map<String, JFieldVar> fields = definedClass.fields();
JMethod toString =
definedClass.method(JMod.PUBLIC, String.class, "toString");
toString.annotate(Override.class);
JBlock body = toString.body();
JExpression expression = JExpr.lit(definedClass.name() + " [");
boolean first = true;
for (JFieldVar fieldVar : fields.values())
{
if ((fieldVar.mods().getValue() & JMod.STATIC) == JMod.STATIC)
{
continue;
}
if (excludedFieldNames.contains(fieldVar.name()))
{
continue;
}
if (!first)
{
expression = expression.plus(JExpr.lit(", "));
}
expression = expression.plus(JExpr.lit(fieldVar.name()+" = "));
expression = expression.plus(JExpr.ref(fieldVar.name()));
first = false;
}
expression = expression.plus(JExpr.lit("]"));
body._return(expression);
}
}
此处显示了使用 toString
方法生成的 class:
package com.example;
public class Example {
public String exampleString;
protected int exampleInt;
private float exampleFloat;
private String excludedString;
static String staticString;
@Override
public String toString() {
return ((((((((("Example ["+"exampleString = ")+ exampleString)+", ")+"exampleInt = ")+ exampleInt)+", ")+"exampleFloat = ")+ exampleFloat)+"]");
}
}
CodeModel 在每个二进制操作周围插入 (
个方括号 )
这一事实导致代码看起来不那么漂亮。但这是可以理解的:否则,他们将不得不考虑运算符的优先级,并且使用和代码生成本身可能 far 更难。
然而,这个toString
方法的结果将是
Example [exampleString = null, exampleInt = 0, exampleFloat = 0.0]
根据您的示例,这应该是您所期望的。
我正在尝试使用 com.sun.codemodel.JCodeModel
.
我已经成功地生成了 hashcode()
和 equals()
方法,但我正在为 toString()
;
我需要以下toString()
实施
return "ClassName [field1 = " + field1 + ", field2 = " + field2 ... ", fieldN = " + fieldN + "]";
如何创建包含 JExpr.lit(field1.name())
与 JExpr.ref(fieldVar.name())
连接的 JCodeModel
JExpression
?
我所做的就是生成一个类似于以下内容的字符串文字:-
return "ClassName [field1 = field1 + field2 = field2 ... fieldN = + fieldN + ]";
到目前为止,这是我的骨架方法:-
final Map<String, JFieldVar> fields = jclass.fields();
final JMethod toString = jclass.method(JMod.PUBLIC, String.class, "toString");
final Set<String> excludes = new HashSet<String>(Arrays.asList(ruleFactory.getGenerationConfig().getToStringExcludes()));
final JBlock body = toString.body();
for (JFieldVar fieldVar : fields.values()) {
if (excludes.contains(fieldVar.name()) || ((fieldVar.mods().getValue() & JMod.STATIC) == JMod.STATIC)) {
continue;
}
??????????????
}
body._return(?????????);
toString.annotate(Override.class);
这里的关键点可能是你可以使用JExpression#plus
方法将多个JExpression
对象与+
运算符组合起来。
这是一个示例,其中包含简单示例 class 的定义,以及一般生成 toString
方法的方法:
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import com.sun.codemodel.CodeWriter;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.writer.SingleStreamCodeWriter;
public class CodeModelToStringTest
{
public static void main(String[] args) throws Exception
{
JCodeModel codeModel = new JCodeModel();
JDefinedClass definedClass = codeModel._class("com.example.Example");
definedClass.field(JMod.PUBLIC, String.class, "exampleString");
definedClass.field(JMod.PROTECTED, int.class, "exampleInt");
definedClass.field(JMod.PRIVATE, float.class, "exampleFloat");
definedClass.field(JMod.PRIVATE, String.class, "excludedString");
definedClass.field(JMod.STATIC, String.class, "staticString");
createToStringMethod(definedClass, Arrays.asList("excludedString"));
CodeWriter codeWriter = new SingleStreamCodeWriter(System.out);
codeModel.build(codeWriter);
}
private static void createToStringMethod(
JDefinedClass definedClass,
Collection<String> excludedFieldNames)
{
Map<String, JFieldVar> fields = definedClass.fields();
JMethod toString =
definedClass.method(JMod.PUBLIC, String.class, "toString");
toString.annotate(Override.class);
JBlock body = toString.body();
JExpression expression = JExpr.lit(definedClass.name() + " [");
boolean first = true;
for (JFieldVar fieldVar : fields.values())
{
if ((fieldVar.mods().getValue() & JMod.STATIC) == JMod.STATIC)
{
continue;
}
if (excludedFieldNames.contains(fieldVar.name()))
{
continue;
}
if (!first)
{
expression = expression.plus(JExpr.lit(", "));
}
expression = expression.plus(JExpr.lit(fieldVar.name()+" = "));
expression = expression.plus(JExpr.ref(fieldVar.name()));
first = false;
}
expression = expression.plus(JExpr.lit("]"));
body._return(expression);
}
}
此处显示了使用 toString
方法生成的 class:
package com.example;
public class Example {
public String exampleString;
protected int exampleInt;
private float exampleFloat;
private String excludedString;
static String staticString;
@Override
public String toString() {
return ((((((((("Example ["+"exampleString = ")+ exampleString)+", ")+"exampleInt = ")+ exampleInt)+", ")+"exampleFloat = ")+ exampleFloat)+"]");
}
}
CodeModel 在每个二进制操作周围插入 (
个方括号 )
这一事实导致代码看起来不那么漂亮。但这是可以理解的:否则,他们将不得不考虑运算符的优先级,并且使用和代码生成本身可能 far 更难。
然而,这个toString
方法的结果将是
Example [exampleString = null, exampleInt = 0, exampleFloat = 0.0]
根据您的示例,这应该是您所期望的。