5

我想导入一个我已经写在外部文件夹中的类,例如:我的类Example.java位于c:\class\Example.java我的脚本中,比如使用

var importedClass = new JavaImporter("c:\\class\\Example.java");

或者

importClass("c:\\class\\Example.java");

这是在 ScriptEngine rhino 的脚本中
我该怎么做???

4

3 回答 3

5

我了解您想要:

  1. 编译一个Java源文件
  2. 加载编译后的代码
  3. 在某些 JavaScript 中使用结果类

javax.tools包提供了一种编译代码的机制,但如果您没有在 JDK 中运行,ToolProvider.getSystemJavaCompiler()将返回null,您将不得不依赖其他一些编译机制(调用外部编译器;嵌入Eclipse 编译器等)。

Java 字节码(.class二进制文件)可以在运行时通过ClassLoader 加载

为了使加载的类对您的脚本引擎可见,您需要通过ScriptEngineManager(ClassLoader)构造函数提供它们。


编辑:根据要求

public class HelloWorld {
  public void say() {
    System.out.println("Hello, World!");
  }
}

HelloWorld.class这个脚本只是调用 Java 反射 API 来从目录加载和实例化一个类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();
}

我敢肯定,还有更优雅的方法可以做到这一点。

于 2010-06-22T14:11:07.220 回答
1

我会质疑为什么要这样做。

此处列出的解决方案将起作用。问题将是:

  1. 您将拥有一个难以排除故障的带有反射的拼凑解决方案。
  2. 您的客户对在运行时加载的补丁代码满意吗?我工作过的每个地方都不是。
于 2010-06-23T01:33:20.520 回答
0

如果我对您的理解正确,您实际上要做的是加载 Java 类,以便您可以(可能)创建实例等。术语是动态加载而不是导入。

Java 允许您*.class使用该ClassLoader.loadClass(String)方法动态加载字节码文件 ( )。关于这个主题有很多资源;例如,JNDI 教程中的“类加载”页面。准备好花一些时间了解这个话题。特别是,由于您尝试加载不在应用程序正常类路径上的类,因此您需要创建一个新的类加载器来执行此操作。java.lang.ClassLoader该类的 Javadocs 在这里

Java源代码不能直接加载,必须先用Java编译器编译。如果您使用的是现代 JDK 安装,则可以在运行时调用 Java 编译器。但是 JRE 安装不包括 Java 编译器。如果您的平台在运行时有可用的 Java 编译器,您可以通过类的getSystemJavaCompiler()静态方法访问它ToolProvider。再一次,从正在运行的 Java 应用程序中调用 Java 编译器很复杂。

于 2010-06-22T14:05:24.993 回答