1

我的 Java 项目有问题,我有一堆项目(例如 A、B、C…)碰巧在 src.tool.Tools 之类的路径中的工具文件夹中有一个 Tools 类,相同的路径并且所有的类名都相同。

现在,我的项目 Z 在其构建路径中包含所有这些项目(A、B、C……)。如何确保当我导入一个工具类时,我正在导入我真正需要的那个?

更复杂的是,如果在 A.Tool 我有一个方法,如 public int tool(){return 1} 而在 B.Tool 中有另一个方法,如 public int tool(){return 0} 我怎样才能确保我调用该函数我真的很想?

谢谢大家!

4

4 回答 4

3

三个选项:

冒险的方法:确保你真正想要的类首先出现在类路径中,并且每个涉及的类加载器都按该顺序处理它们。这可以非常容易地打破非常混乱的结果。您无法访问该课程的多个版本,您只能控制您获得的课程。不要这样做。

复杂的方法:为您依赖的每个项目创建类加载器,并处理特定的类加载器以加载类。要做到这一点需要做很多工作,您也许可以为此使用 OSGI。仅当您的主要目标是了解类加载器时才这样做。

简单而正确的方法:重构您的项目,使每个项目中的所有包在包名称中都有项目名称(或它的某种表示形式)。这使得每个包名称都是唯一的,您可以毫无问题地访问类(如果您必须在一个地方使用多个工具类,则可能使用完整的限定类名称)当您使用它时,您不妨重命名工具类实际上描述了目的,类和包名称,如“Util”、“Tool”或“Misc”,真的是非常糟糕的代码气味。

于 2013-06-28T08:22:41.493 回答
1

可能使用用户定义的类加载器

每个用户定义的类加载器都是抽象类 ClassLoader 的子类的一个实例。应用程序使用用户定义的类加载器来扩展 Java 虚拟机动态加载并由此创建类的方式。用户定义的类加载器可用于创建源自用户定义源的类。例如,一个类可以通过网络下载、动态生成或从加密文件中提取。

于 2013-06-28T08:13:25.617 回答
1

我认为不可能做你想做的事。如果您有三个类都称为“src.tool.Tools”,Java 并不关心您从哪个 jar 文件中加载它们。如果所有三个项目(我假设这意味着 jar 文件)都具有相同的类,Java 将发生冲突,您无法预测它将加载哪些工具。

确保调用正确的唯一方法是确保其他两个不在类路径中。

您的问题有一个黑客解决方案。您可以为每个项目创建一个新的 ClassLoader,并要求 ClassLoader 为 Tools 类提供所需的项目。然后使用反射,您可以实例化它并调用该方法。由于每个项目都在其自己的 ClassLoader 中,因此三个 Tools 类将不再冲突。

前任:

URLClassLoader a = new URLClassLoader(aJar.toURL(), getClass().getClassLoader());  
Class toolsClass = Class.forName("src.tool.Tools", true, a);  
Method m = toolsClass.getDeclaredMethod("tool");  
Object i = toolsClass.newInstance();  
Object result = m.invoke(instance);  

(从How should I load Jars dynamic at runtime? 中提取的 URLClassLoader 示例?

于 2013-06-28T08:13:42.957 回答
0

假设您的项目 A、B、C 每个都有不同的包命名空间,例如 com.you.A、com.you.B 等,您的 Tools 类现在将在多个位置可用,例如 com.you.A.tool.Tools , com.you.B.tool.Tools 等

因此,当您在项目 Z 中创建 Tools 类的实例时,您可以在声明对象引用变量时指定要使用的确切类。

private com.you.A.tool.Tools toolsFromA;
private com.you.B.tool.Tools toolsFromB;

调用toolsFromA.tool()将返回 1,调用toolsFromB.tool()将返回 0。

于 2013-06-28T08:13:13.693 回答