gpt4 book ai didi

java - 是否有生成 Java 源代码来创建对象的 Java 库?

转载 作者:搜寻专家 更新时间:2023-11-01 03:20:36 25 4
gpt4 key购买 nike

我正在寻找一个 API 来生成源代码,它会生成与我传递给库的对象相同的对象。

public static void main(String[] args) {
int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;

// looking for this one
MagicCode.generateCode(arr);
}

应该生成

  int[] arr = new int[3];
arr[0] = 3;
arr[1] = 4;
arr[2] = 5;

  int[] arr = new int[] { 3, 4, 5 };

所以我想传递一个对象并获取 Java 源代码,它会创建一个与我的初始对象相同的对象。

这不仅适用于基本类型,也适用于我自己的对象:

public static void main(String[] args) {
Condition condition = new Condition();
condition.setNumber(2);

// looking for this one
MagicCode.generateCode(condition);
}

应该生成

  Condition c1 = new Condition();
c1.setNumber(2);

作为一个字符串,然后可以将其粘贴到 Java 源文件中。

编辑

我不想绕过编译器。

我将要重写一个没有经过良好测试的组件。所以大约有1000个测试用例要写。功能基本上是输入/输出。我有 1000 个输入字符串,想测试重写组件后它的行为是否完全相同。

因此我想让每个对象都实现#toString() 以便它创建Java 源来创建自己。然后我可以传递我的 1000 个字符串,让当前的实现编写测试用例来确保组件的行为。

最佳答案

代码生成很有趣!您可以通过使用反射来实现您所需要的,遗憾的是,目前还没有实现 MagicCode

你需要使用内省(introspection)来读取什么样的对象并根据它创建它。

您可以使用 Eclipse JDT API 创建类。

Generating a compilation unit

The easiest way to programmatically generate a compilation unit is to use IPackageFragment.createCompilationUnit. You specify the name and contents of the compilation unit. The compilation unit is created inside the package and the new ICompilationUnit is returned.

来自docs ,有一个示例片段。

所以你基本上会反省看看对象是什么类型,它们的字段和当前值是什么。然后您将使用此 API 来创建相应的 AST。您的示例可能如下所示。

public class CodeGenerator {

public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Foo foobar = new Foo();

Bar bar = new Bar();
bar.setSomeValue(555d);
foobar.setBar(bar);
foobar.setPrimitiveDouble(23);
foobar.setValue("Hello World!");

CodeGenerator codeGenerator = new CodeGenerator();

String generatedCode = codeGenerator.generateCode(foobar);

System.out.println(generatedCode);

}

int counter = 0;

private String createVariableName(String clazzName) {
return CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, clazzName + getCurrentCounter());
}

public String generateCode(AST ast, List statements, Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String clazzName = object.getClass().getSimpleName();
String variableName = createVariableName(clazzName);

VariableDeclarationFragment newVariable = ast.newVariableDeclarationFragment();
newVariable.setName(ast.newSimpleName(variableName)); // Or clazzName.toCamelCase()

ClassInstanceCreation newInstance = ast.newClassInstanceCreation();
newInstance.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));
newVariable.setInitializer(newInstance);

VariableDeclarationStatement newObjectStatement = ast.newVariableDeclarationStatement(newVariable);
newObjectStatement.setType(ast.newSimpleType(ast.newSimpleName(clazzName)));

statements.add(newObjectStatement);

BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) {
String propertyName = propertyDesc.getName();

if (!shouldIgnore(propertyName)) {

MethodInvocation setterInvocation = ast.newMethodInvocation();

SimpleName setterName = ast.newSimpleName(propertyDesc.getWriteMethod().getName());
setterInvocation.setName(setterName);

Object invoked = propertyDesc.getReadMethod().invoke(object);

if (invoked == null) {
continue;
}

if (Primitives.isWrapperType(invoked.getClass())) {
if (Number.class.isAssignableFrom(invoked.getClass())) {
setterInvocation.arguments().add(ast.newNumberLiteral(invoked.toString()));
}

// TODO: Booleans
} else {

if (invoked instanceof String) {
StringLiteral newStringLiteral = ast.newStringLiteral();
newStringLiteral.setLiteralValue(invoked.toString());
setterInvocation.arguments().add(newStringLiteral);
} else {

String newObjectVariable = generateCode(ast, statements, invoked);
SimpleName newSimpleName = ast.newSimpleName(newObjectVariable);
setterInvocation.arguments().add(newSimpleName);
}

}

SimpleName newSimpleName = ast.newSimpleName(variableName);
setterInvocation.setExpression(newSimpleName);

ExpressionStatement setterStatement = ast.newExpressionStatement(setterInvocation);

statements.add(setterStatement);

}

}

return variableName;
}

public String generateCode(Object object) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
resetCounter();

AST ast = AST.newAST(AST.JLS3);
Block block = ast.newBlock();

generateCode(ast, block.statements(), object);

return block.toString();

}

private int getCurrentCounter() {
return counter++;
}

private void resetCounter() {
counter = 0;
}

private boolean shouldIgnore(String propertyName) {
return "class".equals(propertyName);
}
}

我使用的依赖:

    <dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
<version>3.9.1.v20130905-0837</version>
</dependency>
<dependency>
<groupId>org.eclipse.core</groupId>
<artifactId>runtime</artifactId>
<version>3.9.100-v20131218-1515</version>
</dependency>
<dependency>
<groupId>org.eclipse.birt.runtime</groupId>
<artifactId>org.eclipse.core.resources</artifactId>
<version>3.8.101.v20130717-0806</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>

这是输出的样子:

  Foo foo0=new Foo();
Bar bar1=new Bar();
bar1.setSomeValue(555.0);
foo0.setBar(bar1);
foo0.setPrimitiveDouble(23.0);
foo0.setValue("Hello World!");

这是 Foo 和 Bar 类的声明:

public class Bar {

private double someValue;

public double getSomeValue() {
return someValue;
}

public void setSomeValue(double someValue) {
this.someValue = someValue;
}

}

public class Foo {

private String value;
private double primitiveDouble;
private Bar bar;

public Bar getBar() {
return bar;
}

public double getPrimitiveDouble() {
return primitiveDouble;
}

public String getValue() {
return value;
}

public void setBar(Bar bar) {
this.bar = bar;
}

public void setPrimitiveDouble(double primitiveDouble) {
this.primitiveDouble = primitiveDouble;
}

public void setValue(String value) {
this.value = value;
}
}

我将其添加到 github repository根据要求。

关于java - 是否有生成 Java 源代码来创建对象的 Java 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31539218/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com