文章目录
- 一、OOP-KCLASS 模型
- 二、疑惑
- 2.1 为什么还需要一个 `Class对象`?
- 2.2 `new` 关键字和 `Class.newInstance()` 的区别?
一、OOP-KCLASS 模型
java 采用了field和method分离的方式,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.HashMapclass clazz= Class.forName(str)map = (HashMap)calzz.newInstance();- 当需要改为
LinkedHashMap时,只需要将配置文件改为xxx.xxxx.LinkedHashMap
这里的本质是,new关键字是加载类+创建类的实例为一体,而通过 class对象 创建则是分开的两步,Class.forName(str) 加载类,newInstance()创建实例。
















![World of Warcraft [CLASSIC] Timebadge](https://i-blog.csdnimg.cn/direct/6cf87a60f55b4ea89e726f3a512caa38.png)


