答案:
不可以。
在 Java 的实现中,类的加载优先由其父类加载器来完成,也就是双亲委托机制。
我们自定义的 java.lang.String
类,如下图,在最底层的自定义部分,其父类加载器是 Application ClassLoader,而 Application ClassLoader 的父类加载器是 Extension ClassLoader,Extension ClassLoader 的父类加载器是 Bootstrap ClassLoader:
Bootstrap ClassLoader
↑
Extension ClassLoader
↑
Application ClassLoader
↑
Custom ClassLoader
根据父类加载器优先原则,加载过程会层层向上,最终会在顶部的 Bootstrap ClassLoader 中找到java.lang.String
,Bootstrap 加载器将其加载到内存中,忽略自定义 java.lang.String
类。
如果我们自定义一个 com.oomake.String
类,那么在检查过程中,顶部的3
个父类加载器都无法加载到它,才会逐层往下最终落到自定义加载器进行加载。
这种双亲委托机制可以有效避免重复加载,当父亲已经加载了该类的时候,子类 ClassLoader 就不会再夹在一次,确保了类的加载安全。
另外,如果自己写 ClassLoader 来加载自定义的java.lang.String
类可不可以呢?
也不可能,因为针对java.*
开头的类,JVM 的实现中已经保证了必须由 Bootstrap ClassLoader 来加载。
最后,附上顶部三个类加载器对应所在位置:
%JAVA_HOME%/lib
目录下的jar包和类或者或被 -Xbootclasspath
参数指定的路径中的所有类。%JRE_HOME%/lib/ext
目录下的 jar 包和类,或被 java.ext.dirs
系统变量所指定的路径下的 jar 包。classpath
下的所有 jar 包和类。