双亲委派 | 自己写的java.lang.String能用吗?

在JDK中内置了很多类,我们能否自己写一个类去“覆盖”这些内置的类呢?

(正常手段下)不能!

 

Talk is cheap. Show me the code,以下我们尝试自己在src中编写一个java.lang.String,用于“覆盖”JDK中的String。

 

自己在src中编写的java.lang.String源码如下所示(包名和类名都与jdk中的String一致)

package java.lang;

public class String {
    public static void main(String[] args) {
        System.out.println("hello String...");
    }
}

 

但在运行时,会报以下异常:

错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:
   public static void main(String[] args)
否则 JavaFX 应用程序类必须扩展javafx.application.Application

 

 

异常提示:在类 java.lang.String 中找不到 main 方法。

why?

why?

why?

 

因为我们的JVM设计者早就想到了这种情况,担心哪个核心类不小心被你碰巧给重名了,造成运行时的诡异错误。为此(当然还有其他原因),JVM内部存在着一个名为“双亲委派”的机制。

 

双亲委派是JVM在加载类时所遵循的一个机制。简单的说,就是当一个加载器要加载类的时候,自己先不加载,而是逐层向上交由双亲(类似于父亲)去加载;当双亲中的某一个加载器 加载成功后,再向下返回成功。如果所有的双亲和自己都无法加载,则报异常。一句话总结:加载器的层次越高,执行的优先级就越高。

 

双亲委托中各个加载器的层级关系如下所示。

 

 

其中,各个加载类的分类及作用如下所示:

  • JVM自带的加载器
    • 根加载器,Bootstrap :
      加载 jre\lib\rt.jar (包含了Object、String、Math等平时编写代码时 大部分的jdk API);也可以通过JVM参数-Xbootclasspath指定加载某一个jar
    • 扩展类加载器,Extension:加载jre中lib\ext\*.jar中的类 ;也可以通过JVM参数-Djava.ext.dirs指定加载某一个jar
    • AppClassLoader/SystemClassLoader,系统加载器(也称为应用加载器):加载classpath(本题中的src);也可以通过JVM参数-Djava.class.path指定加载某一个类/jar
  • 用户自定义的加载器
    • 都是抽象类java.lang.ClassLoader的子类,用于自定义加载

 

本题,程序在执行时识别的是src中的java.lang.String,src就是classpath,因此会调用系统加载器。但根据双亲委派机制,系统加载器会逐层委派双亲来加载此类,在委派的时候,最上层的加载器是根加载器,即根加载器优先级最高。而根加载器能够在jre\lib\rt.jar包中找到一个重名的java.lang.String(即jdk自带的String),因此根据双亲委派最终会由最顶层的根加载器来执行jdk自带的java.lang.String。显然,jdk中的String并没有main()方法,因此报错找不到main()!!!

 

--- 完 ---

 

 

【热文推荐】

服了,list.add()也会报错!!!

技术面试,这些坑你踩过几个?

1行代码实现高性能单例模式

10行代码2道题,全答对的你月薪多少了?

一道JVM面试题,答错率超90%

答疑 | synchronized有指令重排序的功能吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值