文章目录
- 一、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.HashMap
class clazz= Class.forName(str)
map = (HashMap)calzz.newInstance();
- 当需要改为
LinkedHashMap
时,只需要将配置文件改为xxx.xxxx.LinkedHashMap
这里的本质是,new
关键字是加载类+创建类的实例为一体
,而通过 class对象
创建则是分开的两步,Class.forName(str)
加载类,newInstance()
创建实例。