我想导入一个我已在外部文件夹中编写的类,
例如 :
我的班级Example.java
位于c:\class\Example.java
我的脚本中,如使用
var importedClass = new JavaImporter("c:\\class\\Example.java");
或
importClass("c:\\class\\Example.java");
这是ScriptEngine rhino的脚本 我该怎么办?
答案 0 :(得分:5)
我明白你想:
javax.tools包提供了一种编译代码的机制,但是如果你没有在JDK中运行,ToolProvider.getSystemJavaCompiler()将返回null
,你将不得不依赖其他一些代码。编译机制(调用外部编译器;嵌入Eclipse编译器等)。
Java字节码(.class
二进制文件)可以在运行时通过ClassLoader加载。
为了使加载的类对脚本引擎可见,您需要通过ScriptEngineManager(ClassLoader)构造函数提供它们。
编辑:根据要求
public class HelloWorld {
public void say() {
System.out.println("Hello, World!");
}
}
此脚本只调用Java反射API从HelloWorld.class
目录加载并实例化类C:\foo\bin
:
function classImport() {
var location = new java.net.URL('file:/C:/foo/bin/');
var urlArray = java.lang.reflect.Array.newInstance(java.net.URL, 1);
urlArray[0] = location;
var classLoader = new java.net.URLClassLoader(urlArray);
return classLoader.loadClass("HelloWorld");
}
var myClass = classImport();
for(var i=0; i<10; i++) {
myClass.getConstructor(null).newInstance(null).say();
}
我确信有更优雅的方法可以做到这一点。
答案 1 :(得分:1)
我会质疑为什么这样做。
此处列出的解决方案可行。问题是:
答案 2 :(得分:0)
如果我理解正确,你实际上要做的是加载Java类,以便(可能)创建实例,等等。这个术语是动态加载而不是导入。
Java允许您使用*.class
方法动态加载字节码文件(ClassLoader.loadClass(String)
)。这个主题有很多资源;例如JNDI教程中的“Class Loading”页面。准备好花点时间了解这个话题。特别是,由于您正在尝试加载不在应用程序的正常类路径上的类,因此您需要创建一个新的类加载器来执行此操作。 java.lang.ClassLoader
类的Javadoc是here。
Java源代码不能直接加载,但必须首先使用Java编译器进行编译。如果您使用的是现代JDK安装,则可以在运行时调用Java编译器。但是JRE安装不包括Java编译器。如果您的平台在运行时具有可用的Java编译器,则可以通过ToolProvider
类的getSystemJavaCompiler()
静态方法访问它。再一次,从正在运行的Java应用程序中调用Java编译器很复杂。