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

edqdpe6u  于 2023-02-02  发布在  Java
关注(0)|答案(5)|浏览(385)

我有一个java项目,它使用了两个导入的jar,它们具有相同的类(com.sun.mail.imap.IMAPFolder)。有没有办法在导入类时显式地指定要使用哪个jar?使用:

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中构建这个项目。

euoag5mw

euoag5mw1#

当一个类被加载时,第一个与所请求的全限定名匹配的实现将被返回,并且对相关的ClassLoader是可见的。任何其他具有相同全限定名的实现实际上对该ClassLoader是隐藏的。
在标准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!

8gsdolmq

8gsdolmq2#

你不能只在你的Java源代码中做你要求的事情,Java不是为此而设计的。
这是一个糟糕的情况,只能用定制类加载器可靠地处理,每个类加载器提供一个您需要的jar。既然您一开始就在问这个问题,这可能不是您应该走的路,因为这会带来很多新的耗时问题。
我强烈建议您找出 * 为什么 * 您的类路径中有同一个jar的两个不同版本,并重新编写您的程序,以便您只需要一个版本。

sz81bmfz

sz81bmfz3#

是的,有一种方法可以解决这个问题。在我的场景中,我有两个同名同路的类,eclipse总是导入错误的一个。我所做的是改变构建路径中的jar顺序,eclipse将选择构建路径中的第一个。

pengsaosao

pengsaosao4#

如果您使用的是IDE,则可以设置将文件导出到类加载器的顺序。
我在Eclipse上工作,我使用Maven。当我使用Maven安装项目时,它产生了许多额外的jar(我没有在依赖项中定义),并且有一个文件org.w3c.dom.Element存在于2个jar文件中,同一文件的第三个示例也存在于JRE 7中。
为了确保选择正确的文件,我所要做的就是进入Java构建路径-〉Order and Export.选择我希望类加载器给予更多优先权的Jar文件,并使用按钮“Up”将其上移。
x1c 0d1x请注意,这张图片是针对eclipse的,但对于其他IDE,肯定会有类似的方法来解决这个问题。

s2j5cfk0

s2j5cfk05#

1)一般而言:是的,您可以在不同的. jar文件中拥有相同的类:你只需要用一个完全限定的包名来消除它们的歧义。"Date"类(存在于java.util和java.sql中)就是一个很好的例子。
2)如果你有两个 * DIFFENT . jar文件,它们有 * SAME * 完全限定的包名......很有可能,你遇到了冲突。即使你可以通过使用类加载器来解决InvocationTargetException,你仍然可能遇到其他问题。在这种情况下,听起来你的两个. jar文件可能有两个不同的JavaMail API实现。我不知道。
3)最安全的做法是满足所有程序的引用,
而不 * 冒冲突的风险。我相信,如果您从Oracle的JavaMail网页获取"官方". jar,您可以做到这一点:
https://java.net/projects/javamail/pages/Home
"希望能有所帮助!

相关问题