我有一个java项目,它使用两个具有相同类(com.sun.mail.imap.IMAPFolder
)的导入jar。有没有办法明确说明在导入类时使用哪个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中构建项目。
答案 0 :(得分:17)
加载类时,匹配相关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!
答案 1 :(得分:9)
您无法在Java源代码中执行您所要求的操作。 Java不是为此而设计的。
这是一个糟糕的情况,只能通过自定义类加载器可靠地处理,每个加载器都提供您需要的其中一个罐子。既然你首先要问这个问题,这可能不是你应该去的方式,因为这会带来很多新的耗时问题。
我强烈建议您找出为什么您在类路径中有两个不同版本的同一个jar并重新编写程序,因此您只需要一个版本。
答案 2 :(得分:0)
1)通常:是的,您可以在不同的.jar文件中使用相同的类:您只需使用完全限定的包名称消除它们的歧义。 “Date”类(存在于java.util和java.sql中)就是一个很好的例子。
2)如果您有两个不同 .jar文件,这些文件具有 SAME 完全限定的软件包名称...可能性,您就会发生冲突。即使您可以通过使用类加载器来破解InvocationTargetException,您仍可能遇到其他问题。在这种情况下,听起来好像你的两个.jar文件有两个不同的JavaMail API实现。我不知道。
3)最安全的选择是满足您所有程序的参考没有冒着冲突的风险。我相信如果您从Oracle的JavaMail网页上获取“官方”.jar,您可以这样做:
https://java.net/projects/javamail/pages/Home
'希望有所帮助!
答案 3 :(得分:0)
是的,有办法解决这个问题。在我的场景中,我有两个具有相同名称和相同路径的类,eclipse总是导入错误的类。我所做的是更改构建路径中的jar顺序,eclipse将选择构建路径中的第一个。
答案 4 :(得分:0)
如果您使用的是IDE,则可以设置将文件导出到类加载器的顺序。
我在eclipse上工作,我使用maven。当我使用maven安装项目时,它产生了许多额外的jar(我没有在我的依赖项中定义)并且有一个文件org.w3c.dom.Element
存在于2个jar文件中,同一个文件的第3个实例也存在于JRE7中
为了确保获取正确的文件,我所要做的就是转到 Java Build Path - > 订单和导出。选择Jar文件,我希望类加载器提供更多的首选项,并使用按钮" Up"来移动它。