Java:项目中具有相同类的两个jar。

2022-09-04 05:32:41

我有一个java项目,它使用两个具有相同类()的导入jar。有没有办法明确说明在导入类时使用哪个jar?用:com.sun.mail.imap.IMAPFolder

import com.sun.mail.imap.IMAPFolder; 

似乎按照构建路径顺序使用类,但由于某种原因,情况似乎并非如此

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoSuchMethodError: com.sun.mail.imap.IMAPFolder.idle()V
        at com.woodbury.GCM.HelperGmailMonitor.doEmail(HelperGmailMonitor.java:104)
        at com.woodbury.GCM.Launch.listen(Launch.java:16)
        at com.woodbury.GCM.Launch.main(Launch.java:10)
        ... 5 more

在运行时。我正在用eclipse构建这个项目。


答案 1

装入类时,与请求的完全限定名匹配的第一个实现(对相关类可见)是返回的内容。具有相同完全限定名称的任何其他实现实际上都隐藏在 .ClassLoaderClassLoader

这在标准 Java SE 应用程序中意味着,在类路径上列出的第一个代码库(即 jar)与所需的类一起提供它,并且所有其他代码库对同一完全限定类的实现都是隐藏的。

例:

假定 A.jar 包含已编译的类

package com.stackoverflow.example;
public class Hello {
     public static String getGreeting(){
         return "Hello, A!"
     }
}

假定 B.jar 包含已编译的类

package com.stackoverflow.example
public class Hello {
     public static String getGreeting(){
         return "Hello, B!"
     }
}

请注意,在上述两个类中,具有相同的完全限定名。

假设主类是

   import com.stackoverflow.example.Hello;

   public class ExampleMain {
       public static void main(String[] args){
            System.out.println(Hello.getGreeting());
       }
   }

如果我要调用我的程序

java -cp A.jar:B.jar ExampleMain

输出为:Hello, A!

如果我像这样反转类路径

java -cp B.jar:A.jar ExampleMain

输出为:Hello, B!


答案 2

你不能只在你的Java源代码中做你要求的事情。Java不是为此而设计的。

这是一个糟糕的情况,只能使用自定义类装入器可靠地处理,每个装入器都提供您需要的一个jar。由于您首先要问这个问题,因此这可能不是您应该走的方式,因为这会打开很多新的耗时问题。

我强烈建议你找出为什么你的类路径中有两个不同版本的同一jar,并重新编写你的程序,这样你只需要一个版本。