[英]Create a java class dynamically and compile and instantiate at run time
我有一個String
,我需要將其轉換為 java 類,在運行時編譯並創建一個實例:假設我的String
是:
String s = " public class Test {
public Double add(Double x, Double y){
return (x+y);
}
}"
如何將其轉換為類Test
.class,實例化它並在運行時調用方法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);
我們甚至可以在運行時使用反射生成它
我們可以在源代碼中導入類。
Byte Buddy 工作在字節碼級別,不處理源代碼。 您可以為此目的使用 Javassist,它提供對源代碼的有限處理,因為它提供了自己的編譯器。
或者,按照建議使用 Java 編譯器 API。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.