问题请参见标题,高手请掠过。如果不看下面的内容,你自己先想想,会是怎样个情况呢?
我一开始也不得而知,猜测可能会发生冲突,实际情况是不是这样呢?动手编码试试吧。
编码环境,windows 7, jdk1.7.0_45
要想验证这个问题,就要构造两个同样包名、同样类名、同样方法签名,但实现不同的jar包。
OK,简单起见,就构造一个com.As.java的类,里面就一个方法call();
在同一级目录下创建了2个文件夹,一个为bt1, 一个为bt2. (乱取的名字,没啥意义)
分别在两个目录下创建com文件夹,com下创建As.java。
分别对这两个java文件赋予不同的实现。
bt1\com\As.java
package com;
/**
* @author zhongrui
* @Type As.java
* @Desc
* @date 2016/6/26 21:13
*/
public class As {
public String call() {
return "Hello bt1";
}
}
package com;
/**
* @author zhongrui
* @Type As.java
* @Desc
* @date 2016/6/26 21:13
*/
public class As {
public String call() {
return "Hello bt2";
}
}
在回到bt1 和 bt2 的上级目录,分别用javac 和jar命令编译打包。生成bt1.jar 和bt2.jar
在这个目录下写一个Main.java类,实现main方法。调用As类中的call方法。
编译Main类,用bt1.jar或者bt2.jar 作为依赖都可以。
然后运行
可以看到,不管是单独用一个jar包,还是同时使用两个jar包,程序都能运行成功,并且有输出,但是仔细分析输出和类路径的关系,就会发现在有冲突包类方法的情况下,jvm是怎样运行的了。 首先是bt1在前,或者单独是bt1依赖的时候,输出结果都是Hello bt1. 在bt2在前或者单独依赖bt2的时候,输出都是Hello bt2.
因此,可以判断,具体加载哪个类,跟JVM发现它的顺序有关,这里是跟配置类路径的先后顺序相关。回想JDK加载类的实现部分,类文件是从URLResource这样的一个资源中获取出来的,具体这里面怎样实现的,就有待进一步考察它的源码实现了。