类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”

简介: 类加载器“如果我定义了一个类名与Java核心类类名相同,那它还能被加载吗?”



       在Java中,如果你定义了一个类名与Java核心类(比如java.lang.Object)相同的类,按照默认的类加载机制,这个自定义类将不会被加载。这是因为类加载器在加载类的过程中会按照双亲委派模型,优先委派给父类加载器去加载类。

双亲委派模型

       双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载

器。不过这里类加载器之间的父子关系一般不是以继承( Inheritance )的关系来实现的,而是通常使用组合(Composition )关系来复用父加载器的代码。

       

双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。

       所以当我们定义一个与系统内置类同名的类时,类加载器的双亲委派模型会使得类加载器首先向上级委派请求加载类,直到达到启动类加载器。如果所有的类加载器都无法加载这个类,那么才会由当前类加载器尝试加载。

       并且Java的核心类是由启动类加载器(Bootstrap Class Loader)加载的,而启动类加载器是用C++实现的,并不是一个普通的Java类加载器。它负责加载核心的Java API,如 java.lang.Object等。当虚拟机遇到与核心类同名的类时,由于双亲委派模型,启动类加载器已经加载了这个核心类,因此不会再委派给应用程序类加载器加载你定义的同名类,从而导致你定义的类不会被加载。

       所以,尽管你可以定义一个类名与Java核心类相同的类,但是在正常情况下,由于双亲委派机制,自定义类不会被加载,而是使用核心类。

那怎么样才能让它加载我这个类呢?

       如果你希望一个类加载器加载你定义的同名类而不使用双亲委派模型,可以考虑以下两种方式:

自定义类加载器

       你可以编写一个自定义的类加载器,重写它的loadClass方法。在这个方法中,你可以控制类的加载逻辑,不再按照双亲委派模型。你可以通过重写loadClass方法,自己定义加载规则,确保你的类被加载。

public class CustomClassLoader extends ClassLoader {
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        // 自定义加载逻辑,确保加载你的类
        if ("java.lang.Object".equals(name)) {
            return findClass(name);
        }
        return super.loadClass(name);
    }
}
使用线程上下文类加载器

       在一些特殊情况下,你可以使用线程上下文类加载器(Thread Context Class Loader)。线程上下文类加载器是由线程的创建者设定的,它可以独立于双亲委派模型加载类。你可以在代码中通过Thread.currentThread().setContextClassLoader()来设置线程上下文类加载器,使得该线程在加载类时使用你指定的类加载器。

Thread.currentThread().setContextClassLoader(new CustomClassLoader());

       值得注意的是,自定义类加载器需要继承自ClassLoader类,并实现findClass方法来定义类的加载逻辑。使用自定义类加载器需要小心,确保不破坏Java类加载的一些基本规则,以避免出现类加载的冲突和问题。

相关文章
|
4月前
|
Java 编译器 API
Java 密封类:精细化控制继承关系
Java 密封类:精细化控制继承关系
326 83
|
2月前
|
安全 Java 数据建模
Java记录类:简化数据载体的新选择
Java记录类:简化数据载体的新选择
219 101
|
2月前
|
安全 Java 开发者
Java记录类:简化数据载体的新方式
Java记录类:简化数据载体的新方式
272 100
|
3月前
|
安全 IDE Java
Java记录类型(Record):简化数据载体类
Java记录类型(Record):简化数据载体类
367 120
|
29天前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
80 4
|
1月前
|
IDE JavaScript Java
在Java 11中,如何处理被弃用的类或接口?
在Java 11中,如何处理被弃用的类或接口?
134 5
|
1月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
118 1
|
1月前
|
Java Go 开发工具
【Java】(8)正则表达式的使用与常用类分享
正则表达式定义了字符串的模式。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
179 1
|
1月前
|
存储 Java 程序员
【Java】(6)全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
java.util 包提供了 Date 类来封装当前的日期和时间。Date 类提供两个构造函数来实例化 Date 对象。第一个构造函数使用当前日期和时间来初始化对象。Date( )第二个构造函数接收一个参数,该参数是从1970年1月1日起的毫秒数。
128 0
|
1月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
132 1