如何从不同的罐子加载相同的类

时间:2010-05-18 01:27:21

标签: java jar

我在两个不同的jar jar1&中有一个Client.java类。 jar2 现在在运行时我想决定加载哪个Client.class

if (country==india){
         // load Client class of jar1
) else{
        load client class from jar2 
}
我能做到吗......

4 个答案:

答案 0 :(得分:7)

如果2个类具有相同的包名,即com.mycompany.Client,那么最终会导致加载哪个版本的Client有些随意。它归结为首先在类路径上。这是JAR地狱的情况http://en.wikipedia.org/wiki/Java_Classloader#JAR_hell

这是一个要避免的好情况,但是如果你必须拥有同一个类的不同版本,那么有办法做到这一点。一种方法是使用自定义类加载器,类加载器将知道您需要执行哪个版本。这不是一件容易的事情,而且难以管理。 OSGi框架是帮助管理它的另一种选择(它使用自定义类加载器),但如果你只有一个类的实例,我就不会使用它,因为它是另一个需要时间和维护的框架。

底线:如果可以的话,避免这种情况,如果你不能,就采取阻力最小的路径。

如果这些类具有不同的包名,@ Casidiablo提供了一个很好的答案。

答案 1 :(得分:4)

您必须使用路径的“完整”名称。例如:

if (country==india){
         name.first.package.Client client = new name.first.package.Client();
} else{
         name.second.package.Client client = new name.second.package.Client();
}

无论如何......我会尽量避免做那样的事情......这会让你的代码难以阅读和维护。

答案 2 :(得分:3)

如果你真的有两个副本,一个具有完全相同的完全限定名称的类,在两个罐子中,那么......

如果您想要安全,则不应将 中的 放在默认类加载器的类路径中。您将需要创建另外两个类加载器,并在每个加载器中放入一个jar。您将需要为这两个类获取一个类,并且您将需要使用反射来创建您想要的实例。

答案 3 :(得分:0)

我认为你有两种方式:

1)定义一个接口客户端,并实现不同的类,例如:IndiaClient和Country2Client;然后


    interface Client {...}
    class IndiaClient implements Client {...}
    class Country2Client implements Client {...}

    Client client;
    if (country==india){
        client = new IndiaClient();
    ) else{
        client = new Country2Client();
    }

2)在2个不同的jar文件中使用相同的类名继续使用,但仍需要接口或超类,并使用不同的ClassLoader加载Client类:


    interface IClient {...}
    class Client implements IClient {...} // in jar1
    class Client implements IClient {...} // in jar2

    Class<IClient> clientClass;
    if (country==india){
        clientClass = classLoader1.loadClass("package.Client");
    ) else{
        clientClass = classLoader2.loadClass("package.Client");
    }
    IClient client = clientClass.newInstance();

  • 至于如何获取classLoaders,可以参考JDK文档。