在运行时查找新的Java类

8
我有一个功能希望提供给我们正在准备的软件模型的客户,我想知道它是否:
1. 可能实现 2. 智能化(即不愚蠢) 3. 最好的选择
我希望客户能够编写实现我的“Computable”接口的Java类,并将其放入预定文件夹中。该文件夹将包含.java文件而不是.class文件。然后,在运行时,我希望我的程序搜索该文件夹并从该文件夹中提取所有的“Computables”,并将它们存储在一个映射中,从“Computable”的名称到“Computable”对象。 “Computable”应该只有一个默认构造函数,且该接口只有一个名为“compute”的方法,该方法将一个Object数组映射到一个Object。

你想在运行时编译用户的文件吗? - jedierikb
它必须是该语言本身吗,或者另一种脚本语言也可以吗? - skaffman
如果在运行时编译足够容易,那就没问题。我只是不想让客户担心携带类文件。 - JnBrymn
@skaffman 对于 Java 友好的客户端,应该坚持使用 Java。 - JnBrymn
甚至没有像Groovy这样紧密绑定Java的脚本语言吗? - skaffman
8个回答

9

请注意,此API仅在JDK中可用,而不在JRE中。因此,如果您打算分发它,则最终用户/客户端必须安装JDK,这在主要公众中相当罕见。 - BalusC
@BalusC,javax末尾的“x”是否总是意味着这个? - JnBrymn
不,它并不总是这样。有些已经成为了标准的Java SE API的一部分,而其他一些则没有。 - BalusC

3
你可能会发现Google Reflections很有用,可以在类路径中查找实现/扩展某个接口/超类的类。然后就像这样简单明了:
Reflections reflections = new Reflections("my.project.prefix");
Set<Class<? extends SomeClassOrInterface>> subTypes = reflections.getSubTypesOf(SomeClassOrInterface.class);

接下来,为了测试它是否确实有一个无参默认构造函数,只需检查每个类是否 Class#newInstance() 不会抛出任何异常。


那么如果.class文件不在当前路径上,而是在我们只能在运行时了解到的文件夹中呢? - JnBrymn
1
您可以使用URLClassLoader在运行时添加类路径。 - BalusC

2

1
如果在运行时容易编译,那就可以了。您可以使用 {{link1:javax.tools}} 按需进行编译。{{link2:使用javax.tools创建动态应用程序}} 也可能有所帮助。还可以 {{link3:在内存中}} 进行编译。
一个注意点:使用编译器会产生对JDK的依赖;仅使用JRE是不够的。

你有任何样例代码吗?我如何从Java中调用命令行来执行javac?如何读取类文件并构造类? - JnBrymn

0

看起来很有前途,但它似乎围绕着两种可能的解决方案。1)使用某个人为自己构建的API(我不想冒在我剩下的时间内玩别人框架的风险)。或者2)使用反射来找出已加载的类中实现“Computable”的哪些类。记住,我的类尚未被加载...它们只是.java文件。 - JnBrymn

0

我认为如果您允许客户使用类似于Groovy的东西输入代码声明,这将会更简单,它足够接近Java,并且可以轻松地从字符串值在运行时执行。


Groovy不是一个严格的超集吗?如果是这样,我想你可以告诉你的客户它是Java,他们就不会有任何疑问了。 - Mark Peters
啊,我错了。Java文件几乎总是有效的Groovy代码,但它并不是严格的超集。 - Mark Peters

0

遍历文件夹中的文件列表很容易。有人提到可以从Java调用Java编译器(如果重新分发JDK,这是需要检查合法性的一点!!)这已经解决了大部分问题。

你似乎在脑海里构建了一个固定模型,只从文件夹中提取符合特定接口的文件。我认为这是你的方法需要改进的地方。明智的方式(依我之见)是编译该文件夹中的所有文件,然后将它们的类存储在某个地方,在那里您可以加载和反映它们,然后确定哪些实现了接口,哪些没有实现。那些没有实现的会被不必要地加载到您的JVM中,但除非故意浪费空间,否则您不执行的代码不会对程序造成任何伤害。

确定哪些执行可计算操作,然后将这些类(或其实例)存储在集合中,您可以随意使用它们。你只需要忽略其他的。


0
你可以使用BeanShell。这个库很小,不需要JDK。它被用在许多IDE和Web服务器中。最新版本似乎具有从类路径加载.java文件所需的支持。(仍处于beta版)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接