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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19339670/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 16:15:55  来源:igfitidea点击:

Java: Two jars in project with same class.

javaeclipseclassjarimport

提问by Fenrir

I have a java project that is using two imported jars with the same class (com.sun.mail.imap.IMAPFolder). Is there a way to explicitly say which jar to use when importing the class? Using:

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

import com.sun.mail.imap.IMAPFolder; 

would seem to use the class in order of build path order but this does not seem to be the case for some reason causing

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

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

at runtime. I am building the project in eclipse.

在运行时。我正在 eclipse 中构建项目。

采纳答案by Thorbj?rn Ravn Andersen

You cannot do what you ask just in your Java source. Java was not designed for that.

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

This is a bad situation which can only be handled reliably with custom class loaders, each providing one of the jars you need. Since you are asking this question in the first place this is probably not the way you should go yet since that opens up a LOT of new time consuming problems.

这是一种糟糕的情况,只能使用自定义类加载器来可靠地处理,每个类加载器都提供您需要的一个 jar。由于您首先提出这个问题,这可能不是您应该采取的方式,因为这会带来很多新的耗时问题。

I would strongly suggest you find out whyyou have two different versions of the same jar in your classpath and rework your program so you only need one version.

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

回答by Dev

When a class is loaded, the first implementation that matches the requested fully qualified name that is visible to the relevant ClassLoaderis what gets returned. Any other implementations with the same fully qualified name are effectively hidden to that ClassLoader.

当一个类被加载时,与相关的可见的请求的完全限定名称匹配的第一个实现将ClassLoader被返回。具有相同完全限定名称的任何其他实现都被有效地隐藏ClassLoader

What this means in a standard Java SE application is that the first code base (i.e. a jar) listed on the classpath with the required class, provides it, and all other code bases' implementations of the same fully qualified class are hidden.

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

Example:

例子:

Assume that A.jar contains the compiled class

假设 A.jar 包含编译后的类

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

Assume that B.jar contains the compiled class

假设 B.jar 包含编译后的类

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

Note that in both of the above classes have the same fully qualified name.

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

Assume main class is

假设主类是

   import com.stackoverflow.example.Hello;

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

If I were to invoke my program with

如果我要调用我的程序

java -cp A.jar:B.jar ExampleMain

java -cp A.jar:B.jar ExampleMain

the output is: Hello, A!

输出是: Hello, A!

If I reverse the classpath like so

如果我像这样反转类路径

java -cp B.jar:A.jar ExampleMain

java -cp B.jar:A.jar ExampleMain

the output is: Hello, B!

输出是: Hello, B!

回答by paulsm4

1) In general: Yes you can have the same class in different .jar files: you just disambiguate them with a fully qualified package name. The "Date" class (present in java.util and java.sql) is a good example.

1) 一般而言:是的,您可以在不同的 .jar 文件中使用相同的类:您只需使用完全限定的包名称来消除它们的歧义。“Date”类(出现在 java.util 和 java.sql 中)就是一个很好的例子。

2) If you have two DIFFERENT.jar files that have the SAMEfully qualified package names ... chances are, you've got a conflict. Even if you can hack around the InvocationTargetException by playing with the class loader, you might still encounter other problems. In this case, it sounds like maybe your two .jar files have two different implementations of the JavaMail API. I don't know.

2) 如果您有两个不同的.jar 文件,它们具有相同的完全限定包名称......很可能,您遇到了冲突。即使您可以通过使用类加载器来绕过 InvocationTargetException,您仍然可能会遇到其他问题。在这种情况下,听起来您的两个 .jar 文件可能有两种不同的 JavaMail API 实现。我不知道。

3) The safest bet is to satisfy all your program's references WITHOUTrisking a conflict. I believe if you took took the "official" .jar's from Oracle's JavaMail web page, you can do this:

3)最安全的办法是满足你所有的程序的引用冒着冲突。我相信如果您从 Oracle 的 JavaMail 网页上获取了“官方”.jar,您可以这样做:

https://java.net/projects/javamail/pages/Home

https://java.net/projects/javamail/pages/Home

'Hope that helps!

'希望有帮助!

回答by biao li

Yes, there is a way to fix the issue. In my scenario, I have two classes with same name and same path and eclipse always imports the wrong one. What I have done is changing the jar order in the build path and eclipse will pick the first one in the build path.

是的,有办法解决这个问题。在我的场景中,我有两个具有相同名称和相同路径的类,而 Eclipse 总是导入错误的类。我所做的是更改构建路径中的 jar 顺序,eclipse 将选择构建路径中的第一个。

回答by user1295300

If you are using an IDE, you can set the order of exporting the files to the class loader.

如果您使用的是 IDE,则可以设置将文件导出到类加载器的顺序。

I work on eclipse and I use maven. When I install the project using maven, it produced many extra jars (which i hadnt defined in my dependencies) and there was a file org.w3c.dom.Elementwhich was present in 2 jar files and 3rd instance of the same file was also in JRE7.

我在 eclipse 上工作,我使用 maven。当我使用 maven 安装项目时,它产生了许多额外的 jar(我没有在我的依赖项中定义)并且有一个文件org.w3c.dom.Element存在于 2 个 jar 文件中,并且同一文件的第三个实例也在 JRE7 中。

In order to make sure the correct file is picked up, all I had to do was to go to Java Build Path-> Order and Export. Select the Jar file I wanted the classloader to give more preference and move it up with the button "Up".

为了确保选择正确的文件,我所要做的就是转到Java Build Path-> Order and Export。选择我希望类加载器给予更多偏好的 Jar 文件,然后使用“向上”按钮将其向上移动。

This is how it looks. Eclipse - Java Build Path ->Order and ExportPlease note that this image is for eclipse. But for other IDEs there would definitely be a similar way to work this out.

这是它的样子。 Eclipse - Java 构建路径 ->订购和导出请注意,此图像用于日食。但是对于其他 IDE,肯定会有类似的方法来解决这个问题。