java - 动态创建java类并在运行时编译实例化
问题描述
我有一个String
需要转换为 java 类,在运行时编译并创建一个实例:假设我String
是:
String s = " public class Test {
public Double add(Double x, Double y){
return (x+y);
}
}"
如何将它转换为类.class,实例化它并在运行时Test
调用该方法?add(Double x, Double y)
我读到了Byte
Buddy ,但我看到的例子已经定义了一个类。在上述情况下,任何人都可以举一个例子,我如何使用 ByteBuddy 或任何其他可以实现这一目标的库?
任何有关如何将其转换String
为可编译和可实例化的 java 类的输入或建议都会有所帮助。
解决方案
我们可以使用这样的东西:
package com.demo;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
public class StringToClass
{
public static void main(String[] args)
{
String s = "import com.demo.FormulaAPI; public class FormulaExecutor" +
" { public Double formula1(FormulaAPI apiReference)" +
" { System.out.println(apiReference.evaluate(\"10.10\")); return apiReference.evaluate(\"10.10\"); } }";
try
{
dynamicClass(s, "FormulaExecutor");
} catch (IOException | NoSuchMethodException | ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e)
{
e.printStackTrace();
}
}
static void dynamicClass(String sourceCode, String className) throws IOException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException
{
File parent = new File(System.getProperty("user.dir"));
File sourceFile = new File(parent, className + ".java");
sourceFile.deleteOnExit();
FileWriter writer = new FileWriter(sourceFile);
writer.write(sourceCode);
writer.close();
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);
File parentDir = sourceFile.getParentFile();
standardJavaFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(parentDir));
Iterable<? extends JavaFileObject> compilationUnits = standardJavaFileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile));
javaCompiler.getTask(null, standardJavaFileManager, null, null, null, compilationUnits).call();
standardJavaFileManager.close();
URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] {parentDir.toURI().toURL()});
Class<?> dynamicClass = urlClassLoader.loadClass(className);
Method formula1 = dynamicClass.getDeclaredMethod("formula1", FormulaAPI.class);
formula1.invoke(dynamicClass.newInstance(), new Object[] {new FormulaAPI()});
}
}
package com.demo;
public class FormulaAPI
{
public Double evaluate(String str)
{
return Double.valueOf(str);
}
}
现在,方法名称是硬编码的
Method addMethod = dynamicClass.getDeclaredMethod("add", Double.class, Double.class);
我们甚至可以在运行时使用反射生成它
我们可以在源代码中导入类。
推荐阅读
- c# - ASP.NET Web API get dto from body with interface type
- ios - 自 iOS 13 以来的手势混淆
- npm - 错误:未找到兼容版本:package-json@'^6.3.0'
- python - 如何删除 Python 中某个值出现在该行中的数据框的行?
- c# - 尝试从缓冲区读取字节到 int 时进程挂起。wkhtmltopdf
- android - 如何从 LibGdx 核心模块检查 Android 运行时权限/获取 Android 当前活动?
- google-signin - 谷歌登录框架是否支持 mac 催化剂?
- c# - 为什么我的列表没有返回正确的总和
- sql - (Teradata) 获取前 12 个月、3 个月和 1 个月的 SUM 值
- flutter - Flutter:奇怪的 SystemUIOverlayStyle 错误