Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 755|回复: 0

[Java基础知识]java JVM如何判断类相同

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-30 17:45:25 | 显示全部楼层 |阅读模式
    上篇中,提到Class生成对象的原理,根据上篇的小例子,得出的结果程序中的Class对象是一样的,是只有一个Class对象.那JVM是如何判断这三个Class对象其实是一个Class对象呢?  JVM根据两个方面判断:一是类的全称;另一个是类加载器.  根据上篇中的结果得出:类的全称是相同的.那类加载器是否相同呢?即使类的全称相同,而使用的加载器不同,那Class对象也是不同的.那我们继续上篇中的例子,看看所使用的加载器的结果如何呢?其中使用getClassLoad()方法.  
      
       
       
         
       

         
       
      
    1.     /**
    2.      * @author: 梁焕月  
    3.      * 文件名:TestClass.java  
    4.      * 时间:2012-2-6上午10:01:52   
    5.      */  
    6.       
    7. public class TestClass {  
    8.   public  static void main(String[] args){  
    9.       
    10.    try {     
    11.     //测试Class.forName()   
    12.     Class testTypeForName=Class.forName("TestClassType");           
    13.     System.out.println("testForName---"+testTypeForName);  
    14.       
    15.     //测试类加载器     
    16.     System.out.println("forName形式的加载器--"+testTypeForName.getClassLoader());  
    17.     //测试类名.class  
    18.     Class testTypeClass=TestClassType.class;  
    19.     System.out.println("testTypeClass---"+testTypeClass);  
    20.       
    21.     //测试类加载器  
    22.     System.out.println(".class形式的加载器---"+testTypeClass.getClassLoader());  
    23.       
    24.     //测试Object.getClass()  
    25.     TestClassType testGetClass= new TestClassType();  
    26.     System.out.println("testGetClass---"+testGetClass.getClass());  
    27.       
    28.     //测试类加载器  
    29.     System.out.println("getClass形式的加载器--"+testGetClass.getClass().getClassLoader());   
    30.       
    31.    } catch (ClassNotFoundException e) {  
    32.       
    33.     // TODO Auto-generated catch block  
    34.       
    35.     e.printStackTrace();  
    36.       
    37.    }     
    38.       
    39.   }  
    40.       
    41. }  
    42.       
    43. class TestClassType{  
    44.       
    45. //构造函数     
    46.    public TestClassType(){  
    47.     System.out.println("----构造函数---");  
    48.    }  
    49.       
    50. //静态的参数初始化  
    51.       
    52.     static{   
    53.       System.out.println("---静态的参数初始化---");  
    54.       
    55.     }  
    56.   
    57.   //非静态的参数初始化  
    58.       
    59.     {  
    60.       
    61.     System.out.println("----非静态的参数初始化---");  
    62.       
    63.     }         
    64.       
    65.     }  
    复制代码
    结果如下:
    C:java>java TestClass
    ---静态的参数初始化---
    testForName---class TestClassType
    forName形式的加载器--sun.misc.Launcher$AppClassLoader@19821f
    testTypeClass---class TestClassType
    .class形式的加载器---sun.misc.Launcher$AppClassLoader@19821f
    ----非静态的参数初始化---
    ----构造函数---
    testGetClass---class TestClassType
    getClass形式的加载器--sun.misc.Launcher$AppClassLoader@19821f

    观察结果发现:三种形式的加载器是相同的.  因此可以说明上篇例子中的三个方式生成的Class对象只有一个.同样也证明了上篇中Class对象生成的原理。JVM首先判断内存中是否已经加载该类。判断的依据就是此篇的介绍。  java中默认的有三种类型加载器。分别是:系统类加载器(应用类加载器)、扩展类加载器、引导类加载器。   例子已经测试了加载器类型是: sun.misc.Launcher$AppClassLoader@f4f44a,这个是系统类加载器。来看一下父类的加载器类型: //测试类加载器
    System.out.println("forName形式的加载器--"+testTypeForName.getClassLoader()); //测试父类加载器
    System.out.println("testTypeForName的父类加载器--"+testTypeForName.getClassLoader().getParent());
    System.out.println("testTypeForName的父类的父类的加载器--"+testTypeForName.getClassLoader().getParent().getParent());  输出的结果如下:
    forName形式的加载器--sun.misc.Launcher$AppClassLoader@f4f44a
    testTypeForName的父类加载器--sun.misc.Launcher$ExtClassLoader@1d256fa
    testTypeForName的父类的父类的加载器--null  结果说明了,系统类加载器的父类是扩展类加载器,扩展类加载器的父类是引导类加载器。他们之间的关系如下:   我们分析三种加载器的使用场合。 1.系统类加载器(应用类加载器),这个加载器使用java实现,使用广泛,负责加载classPath中指定的类。
    具体的使用场合是:加载classPath中指定的而扩展类加载器没有加载的类。若扩展类加载器加载了classPath中的类,则系统类加载器则没有机会加载。
    用户定义的类一般都是系统类加载器加载的。
    可以通过:ClassLoader.getSystemClassLoader()获得。 2.扩展类加载器。
        它负责加载Java的标准扩展,一般使用Java实现的,负责加载jre/lib/ext中的类。和普通的类加载器一样。
    可以通过:ClassLoader.getSystemClassLoader().getParent()获得。 3.引导类加载器。
        它负责加载jdk中的系统类,是用C语言实现的。对于java程序无法获得它,像上文中获得扩展类加载器的父类加载器是null。像 String,Integer,Double类都是由引导类加载器加载的。

    类加载机制的原理是双亲委派机制。
        当加载一个类时,首先把机会让给父类,先让父类加载,若是父类中不能加载,才会自己再加载。(这是孝顺型的,先想到父类) 而那个Tomcat加载器则恰恰相反。 当加载一个类时,首先自己加载,自己加载不了,则再去找父类帮忙。(这个忘恩型的,先想到自己)  


      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 17:28 , Processed in 0.380830 second(s), 48 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表