我的Java项目有问题,我有一堆项目(例如A,B,C ......)碰巧在路径中的工具文件夹中有一个Tools类,例如src.tool.Tools,所有这些路径和相同的类名相同。
现在,我的项目Z在其构建路径中具有所有这些项目(A,B,C ......)。我如何确保在导入一个Tool类时导入我真正需要的那个?
更复杂,如果在A.Tool我有一个方法,如public int tool(){return 1}和B.Tool另一个方法,如public int tool(){return 0}我怎样才能确定我打电话给我真正想要的功能?
谢谢大家!
答案 0 :(得分:3)
三个选项:
危险的方式:确保您真正想要的类在类路径中首先出现,并且涉及的每个类加载器都按此顺序处理它们。这可能会非常容易打破非常混乱的结果。您无法访问该类的多个版本,您只能控制您获得的版本。不要这样做。
复杂的方式:为您依赖的每个项目创建类加载器,并使用特定的类加载器来加载类。要做到这一点需要做很多工作,你可以使用OSGI。只有在您的主要目的是了解班级装载机时才这样做。
简单正确的方法:重构您的项目,以便每个项目中的所有包都具有包名称中的项目名称(或其某种表示形式)。这使得每个包名都是唯一的,您可以毫无问题地访问类(如果您必须在一个地方使用多个工具类,可能使用完全限定的类名)当您使用它时,您也可以将工具类重命名为实际上描述了目的,类和包名称,如“Util”,“Tool”或“Misc”真的是非常糟糕的代码味道。
答案 1 :(得分:1)
可能使用user-defined class loader:
每个用户定义的类加载器都是一个子类的实例 抽象类ClassLoader。应用程序使用用户定义的类 加载器为了扩展Java Virtual的方式 机器动态加载,从而创建类。用户自定义 类加载器可用于创建源自的类 用户定义的来源。例如,可以跨类下载一个类 网络,动态生成或从加密文件中提取。
答案 2 :(得分: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 dynamically at runtime?拉出URLClassLoader示例)
答案 3 :(得分: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.