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

相关文章
|
1月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
143 57
|
3天前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
1月前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
52 8
|
1月前
|
Java 编译器
Java重复定义变量详解
这段对话讨论了Java中变量作用域和重复定义的问题。学生提问为何不能重复定义变量导致编译错误,老师通过多个示例解释了编译器如何区分不同作用域内的变量,包括局部变量、成员变量和静态变量,并说明了使用`this`关键字和类名来区分变量的方法。最终,学生理解了编译器在逻辑层面检查变量定义的问题。
Java重复定义变量详解
|
1月前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
73 17
|
1月前
|
Java Maven Spring
Java Web 应用中,资源文件的位置和加载方式
在Java Web应用中,资源文件如配置文件、静态文件等通常放置在特定目录下,如WEB-INF或classes。通过类加载器或Servlet上下文路径可实现资源的加载与访问。正确管理资源位置与加载方式对应用的稳定性和可维护性至关重要。
57 6
|
1月前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
1月前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
133 4
|
1月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
76 2
|
1月前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
58 4