自学内容网 自学内容网

java 对象模型的个人理解

一、OOP-KCLASS 模型

java 采用了fieldmethod分离的方式,field组成实例 obj ,存储在堆区,而method相关的作为一个 Kclass,存储在方法区,这样子每个对象实例obj只需要持有一个执行指向 Kclass 的指针就可以访问自己的方法了。

示例:(图是网上找的)
在这里插入图片描述
但是需要注意的是,当一个 .class 文件被加载后,其会在堆上同样的创建一个 Class对象(注意不是 Class实例对象 Obj)

因此,堆上保存了每个Class唯一的Class对象以及N个实例对象Obj,方法区存储了该Class的元数据KClass。其中 Class对象实例对象都持有一个指向KClass的指针,KClass其中有一个字段_java_mirror 指向 Class对象

因此,我们可以通过实例对象obj获取到Class对象,路径为:实例对象obj --> KClass --> Class对象
获取 class对象的途径:

  • Class.forName("ClassName"):通过类的元数据(KClass)中的class对象引用获得class对象
  • object.getClass():通过实例对象Obj中保存的对KClass的引用获取类的元数据(instanceKlass),通过instanceKlass中对class对象的引用获取class对象(instanceOopDesc)
  • ClassName.class:通过类的元数据(KClass)中的class对象引用获得class对象

在这里插入图片描述

二、疑惑

2.1 为什么还需要一个 Class对象

Class对象为应用提供了查询方法区Class相关信息的接口,这样子反射才能获取到 Method 等抽象(反射的基础)

Class对象的获取需要通过KClass,这也就是KClass需要持有一个指向Class对象指针的原因(实例对象不直接指向class对象,我的理解是增加直接指向,每个对象需要多加一个成员,浪费内存,而获取class对象进行反射等操作是一个低频的操作)

2.2 new 关键字和 Class.newInstance() 的区别?

这个问题想问的是:Class对象的主要作用是为java应用提供一个灵活的访问方法区内容的接口,而这通常用于反射或者通过Class创建实例对象。那为什么我不在创建实例对象的地方用new关键字呢?

这是因为用 Class 更灵活:

  • 使用 new,必须指定确定的类型,比如 new HashMap,当我想改用 LinkedHashMap 时,需要改代码
  • 使用 class ,则只需要根据配置文件读取配置的类名,无需改动代码就可以实现创建不同对象。例如:
    • String str 读取自配置文件,内容假设为 xxx.xxxx.HashMap
    • class clazz= Class.forName(str)
    • map = (HashMap)calzz.newInstance();
    • 当需要改为LinkedHashMap时,只需要将配置文件改为 xxx.xxxx.LinkedHashMap

这里的本质是,new关键字是加载类+创建类的实例为一体,而通过 class对象 创建则是分开的两步,Class.forName(str) 加载类,newInstance()创建实例。


原文地址:https://blog.csdn.net/sinat_38705282/article/details/140700040

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!