我有一个String
:
public class Hesey {
public void testAdd() {
System.out.println("Hi");
}
}
我是否可以使用一部分API来编译此String
到Class
并加载此类' Class&#39 ;?或者我是否必须使用ToolProvider.getSystemJavaCompiler()
来编译整个源?
答案 0 :(得分:1)
看看OpenHFT Java Runtime Compiler。
它支持将动态提供的Java源代码编译为字符串:
private final CachedCompiler cc = new CachedCompiler(null, null);
Class aClass = cc.loadFromJava(className, javaCode);
Object o = aClass.newInstance(); // instance of the object declared in 'javaCode'
其中javaCode是Java源代码的字符串表示形式。在幕后,我相信它正在使用ToolProvider.getSystemJavaCompiler()。
答案 1 :(得分:1)
AFAIK,Javassist不允许我们从文本中构建一个类。以下是我用于使用该库构建类的代码:
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.NotFoundException;
public class CtClassTemplate {
public static volatile String CLASS_DEBUG_PATH = null;
private final String name;
private String extendsClass;
private final List<String> implementsInterfaces = new ArrayList<>();
private final List<CtFieldTemplate> fields = new ArrayList<>();
private final List<CtMethodTemplate> methods = new ArrayList<>();
public CtClassTemplate(final String name) {
this.name = name;
}
public void setExtends(final String className) {
this.extendsClass = className;
}
public void addImplements(final String ifcName) {
implementsInterfaces.add(ifcName);
}
public CtFieldTemplate addField(final String code) {
final CtFieldTemplate result = new CtFieldTemplate(code);
fields.add(result);
return result;
}
public CtMethodTemplate addMethod(final String code) {
final CtMethodTemplate result = new CtMethodTemplate(code);
methods.add(result);
return result;
}
public <T extends Class> T createClass(final ClassPool pool) throws CannotCompileException {
return createClass(pool, CtClassTemplate.class.getClassLoader());
}
public <T extends Class> T createClass(final ClassPool pool, final ClassLoader cl) throws CannotCompileException {
try {
final CtClass ctClass = pool.makeClass(name);
if (extendsClass != null && !extendsClass.isEmpty()) {
ctClass.setSuperclass(pool.get(extendsClass));
}
for (String ifc : implementsInterfaces) {
ctClass.addInterface(pool.get(ifc));
}
for (CtFieldTemplate field : fields) {
final CtField ctField = CtField.make(field.getCode(), ctClass);
ctClass.addField(ctField);
}
for (CtMethodTemplate method : methods) {
final CtMethod ctMethod = CtMethod.make(method.getCode(), ctClass);
ctClass.addMethod(ctMethod);
}
final String cdp = CLASS_DEBUG_PATH;
if (cdp != null) {
ctClass.writeFile(cdp);
}
return (T) ctClass.toClass(cl, null);
} catch (NotFoundException | IOException e) {
throw new CannotCompileException(e);
}
}
public class CtMethodTemplate {
private String code;
private CtMethodTemplate(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
public class CtFieldTemplate {
private String code;
private CtFieldTemplate(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
}
你可以像这样使用它:
final ClassPool ctPool = new ClassPool(true);
final CtClassTemplate aTmpl = new CtClassTemplate("foopackage.A");
aTmpl.setExtends("foopackage.B");
aTmpl.addImplements("foopackage.CIfc");
aTmpl.addImplements("foopackage.onemorefoopackage.DIfc");
aTmpl.addField("private int i;");
aTmpl.addMethod("public int getI() { return i; }");
aTmpl.addMethod("public void setI(int i) { this.i = $1; }");
final Class aClass = aTmpl.createClass(ctPool);
或者在你的情况下:
final CtClassTemplate aTmpl = new CtClassTemplate("Hesey");
aTmpl.addMethod("public void testAdd() { System.out.println(\"Hi\"); }");
final Class aClass = aTmpl.createClass(ctPool);
不幸的是,并非真正的整篇文章,但主要是:)