Maven项目依赖中同包类被本地类覆盖的行为名称及原理是什么?
问题场景
你有一个dependency项目,定义了如下两个类:
package it.dependency.common; public class Consumer { public void consume() { Worker dependency = new Worker(); dependency.work(); } }
package it.dependency.common; public class Worker { public void work() { System.out.println("I'm doing things in the DEPENDENCY project"); } }
在dependency项目中运行调用consume()方法,会正常输出 I'm doing things in the DEPENDENCY project。
将该项目编译为JAR包后,导入名为test project的项目作为依赖,依赖配置如下:
<dependency> <groupId>org.example</groupId> <artifactId>dependency</artifactId> <version>1.0-SNAPSHOT</version> <systemPath>${lib.path}/dependency-1.0-SNAPSHOT.jar</systemPath> </dependency>
test project中重定义了同包同名的Worker类:
package it.dependency.common; public class Worker { public void work() { System.out.println("I'm doing things in the TEST project"); } }
此时在test project中调用dependency项目Consumer类的consume()方法,输出变为 I'm doing things in the TEST project。
行为名称
该行为叫做类覆盖(Class Shadowing),属于类路径冲突的典型场景,部分资料也会将其称为同全限定名类优先级覆盖。
底层运行原理
该现象是JVM类加载规则的正常表现,核心逻辑如下:
- JVM判断类唯一性的依据是全限定类名(包名+类名)+ 加载类的类加载器实例,两个条件完全一致才会被判定为同一个类。该场景中的两个
Worker类全限定名完全相同,且都由默认的应用类加载器(AppClassLoader)加载,因此JVM只会加载搜索顺序中第一个被找到的类。 - 常规Maven项目运行时,应用类加载器的类搜索优先级为:当前项目编译输出的
classes目录 > 依赖引入的第三方JAR包。test project中自定义的Worker类编译后存放在当前项目的classes目录下,优先级远高于外部引入的dependency JAR包里的同名类,因此会被优先加载。 - 当
Consumer类执行new Worker()逻辑时,会向类加载器请求加载it.dependency.common.Worker,类加载器会直接返回已经完成加载的test project中的Worker类,因此最终执行的是test project中的方法逻辑。
内容的提问来源于stack exchange,提问作者Marco Arnone
相关产品推荐
相关产品推荐

