类加载器“如果我定义了一个类名与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类加载的一些基本规则,以避免出现类加载的冲突和问题。

相关文章
|
7天前
|
Java 关系型数据库 MySQL
Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
【4月更文挑战第12天】Elasticsearch【问题记录 01】启动服务&停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含shell脚本文件)
36 3
|
3天前
|
人工智能 安全 Java
Java8 - LocalDateTime时间日期类使用详解
Java8 - LocalDateTime时间日期类使用详解
|
4天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
4天前
|
安全 Java 程序员
|
5天前
|
Java
Java Class类
Java Class类
8 0
|
10天前
|
Java
Java接口中可以定义哪些方法?
【4月更文挑战第13天】
14 0
Java接口中可以定义哪些方法?
|
11天前
|
Java 编译器
Java Character 类
4月更文挑战第13天
|
12天前
|
存储 Java
Java基础教程(7)-Java中的面向对象和类
【4月更文挑战第7天】Java是面向对象编程(OOP)语言,强调将事务抽象成对象。面向对象与面向过程的区别在于,前者通过对象间的交互解决问题,后者按步骤顺序执行。类是对象的模板,对象是类的实例。创建类使用`class`关键字,对象通过`new`运算符动态分配内存。方法包括构造函数和一般方法,构造函数用于对象初始化,一般方法处理逻辑。方法可以有0个或多个参数,可变参数用`类型...`定义。`this`关键字用于访问当前对象的属性。
|
16天前
|
Java Shell
Java 21颠覆传统:未命名类与实例Main方法的编码变革
Java 21颠覆传统:未命名类与实例Main方法的编码变革
14 0
|
16天前
|
Java
Java 15 神秘登场:隐藏类解析未知领域
Java 15 神秘登场:隐藏类解析未知领域
18 0