我有一个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中构建这个项目。
5条答案
按热度按时间euoag5mw1#
当一个类被加载时,第一个与所请求的全限定名匹配的实现将被返回,并且对相关的
ClassLoader
是可见的。任何其他具有相同全限定名的实现实际上对该ClassLoader
是隐藏的。在标准Java SE应用程序中,这意味着类路径中列出的第一个代码基(例如jar)提供了所需的类,而同一个完全限定类的所有其他代码基的实现都是隐藏的。
示例:
假设A.jar包含编译后的类
假设B.jar包含编译后的类
请注意,在上述两个类中具有相同的完全限定名。
假设主类为
如果我用
java -cp A.jar:B.jar ExampleMain
输出为:
Hello, A!
如果像这样反转类路径
java -cp B.jar:A.jar ExampleMain
输出为:
Hello, B!
8gsdolmq2#
你不能只在你的Java源代码中做你要求的事情,Java不是为此而设计的。
这是一个糟糕的情况,只能用定制类加载器可靠地处理,每个类加载器提供一个您需要的jar。既然您一开始就在问这个问题,这可能不是您应该走的路,因为这会带来很多新的耗时问题。
我强烈建议您找出 * 为什么 * 您的类路径中有同一个jar的两个不同版本,并重新编写您的程序,以便您只需要一个版本。
sz81bmfz3#
是的,有一种方法可以解决这个问题。在我的场景中,我有两个同名同路的类,eclipse总是导入错误的一个。我所做的是改变构建路径中的jar顺序,eclipse将选择构建路径中的第一个。
pengsaosao4#
如果您使用的是IDE,则可以设置将文件导出到类加载器的顺序。
我在Eclipse上工作,我使用Maven。当我使用Maven安装项目时,它产生了许多额外的jar(我没有在依赖项中定义),并且有一个文件
org.w3c.dom.Element
存在于2个jar文件中,同一文件的第三个示例也存在于JRE 7中。为了确保选择正确的文件,我所要做的就是进入Java构建路径-〉Order and Export.选择我希望类加载器给予更多优先权的Jar文件,并使用按钮“Up”将其上移。
x1c 0d1x请注意,这张图片是针对eclipse的,但对于其他IDE,肯定会有类似的方法来解决这个问题。
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
"希望能有所帮助!