能不能自己写个类叫java.lang.System?
网上提供的答案有说可以,通常不可以,但可以采取另类方法达到这个需求
也有博客说不可以的,刚开始学习的时候还比较疑惑,后来完整地学习完了深入理解Java虚拟机后了解了其中的本质。
我的观点是:不可以!!
类加载器可分为两类:一是启动类加载器(Bootstrap ClassLoader),是C++实现的,是JVM的一部分;另一种是其它的类加载器,是Java实现的,独立于JVM,全部都继承自抽象类java.lang.ClassLoader。jdk自带了三种类加载器,分别是启动类加载器(Bootstrap ClassLoader),扩展类加载器(Extension ClassLoader),应用程序类加载器(Application ClassLoader)。后两种加载器是继承自抽象类java.lang.ClassLoader。关于这三种加载器各自的作用这里不做详细说明,有兴趣的可以自己了解下。
类加载器是有层次的
一般是: 自定义类加载器 >> 应用程序类加载器 >> 扩展类加载器 >> 启动类加载器
上面的层次关系被称为双亲委派模型(Parents Delegation Model)。除了最顶层的启动类加载器外,其余的类加载器都有对应的父类加载器。
再简单说下双亲委托机制:如果一个类加载器收到了类加载的请求,它首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器,每一个层次的类加载器都是加此,因此所有的加载请求最终到达顶层的启动类加载器,只有当父类加载器反馈自己无法完成加载请求时(指它的搜索范围没有找到所需的类),子类加载器才会尝试自己去加载。
道理是这样,要验证才知道真伪:
首先自己定义一个包叫做java.lang,然后在里面定义一个类叫做Object.
然后在里面定义一个方法叫做doSomething()
package java.lang; public class Object { public void doSomething() { System.out.println("doSomething"); } }然后在另一个包里面使用Object对象:
package com.test; import java.lang.Object; public class ObjectTest { public static void main(String[] args) { Object o = new Object(); o.doSomething(); } }
运行就会报错java.lang.NoSuchMethodError异常
所以双亲委派模型还是有道理的
所以当我们加载自己写的java.lang.Object时,会默认调用Appliation ClassLoader,这是系统提供的类加载器,肯定支持”双亲委派模型”,所以我们的请求会一步步提交到Bootstrap ClassLoader那里,这个类默认加载的类位于$JAVA_HOME/jre/lib下面的rt.jar包,可以找到我们需要的java.lang.Object类,所以加载的自然就不是我们自己写的Object类了.