在Java中,类也表现为普通的对象,它的类是java.lang.Class
在Java语言中,有两种方式可以获得类对象引用:
- 使用类字面值
String.class
- 调用对象的getClass()方法
"abc".getClass()
类加载
想象这样一个极简化的Java虚拟机运行时状态:方法区中只加载了两个类,java.lang.Object和java.lang.Class;
堆中只通过new指令分配了一个对象。
classLoad每加载一个class 都有这样一步操作
Class jClassClass = classMap.get("java/lang/Class");
Object jClass = jClassClass.newObject();
jClass.extra=class;
class.jClass= jClass;
只有Class的实例 的extra里面才有对类的引用
就是
Class的实例objectPanda=Panda.class 的extra里面有对Panda类的引用
void和基本类型也有对应的类对象,但只能通过字面值来访问:
System.out.println(void.class);
System.out.println(boolean.class);
System.out.println(byte.class);
System.out.println(char.class);
System.out.println(short.class);
System.out.println(int.class);
System.out.println(long.class);
System.out.println(float.class);
System.out.println(double.class);
classLoad初始化时,就会加载Class类
loadClass("java/lang/Class");
Class类继承Object类还实现了一些接口,这些也会被先加载
以后(Class类之前加载的类也会补上)每个类被加载,都会被set它对应的class对象,,这个class对象里面有它的引用
类里面有个 jClass 指向对应的class对象
某class{
.....其他field
//对应xxx.class对象
Object jClass{
Class clazz;//固定是 "java/lang/Class"
Object[] slots;
//记录Object结构体实例的额外信息
Object extra{
Class 某class;
}
}
}
getClass()得其class对象
java/lang/Object.getClass()
是本地方法
this的对应class对象入栈 这样所有类都能用 类名.getClass()来得到对应class对象了
private static final NativeMethod getClass= frame->{
OObject thisObject = frame.getLocalVars().getRef(0);
OObject classObject = thisObject.getClazz().jClass;
frame.getOperandStack().push(classObject);
};
基本类型.class 得class对象
最终是这样得到 java/lang/Class.getPrimitiveClass
private static final NativeMethod getPrimitiveClass =frame -> {
//拿到本基本类的类名
OObject nameStringObject = frame.getLocalVars().getRef(0);//"int"java的String对象
String name = StringPool.getString(nameStringObject);//"int"字符串 本地语言
//从类加载器得到这个基本类→得其对应class对象
MyClassLoader classLoader = frame.getMethod().getClazz().classLoader;
OObject primitiveClassObject = classLoader.loadClass(name).jClass;
//入栈
frame.getOperandStack().push(primitiveClassObject);
} ;
class对象.getName()
//java/lang/Class里面
public String getName() {
String name = this.name;
if (name == null)
this.name = name = getName0();
return name;
}
getName0
是本地方法
private static final NativeMethod getName0 = frame -> {
//class对象
OObject thisClassObject = frame.getLocalVars().getRef(0);
//这个Class类的
CClass clazz = (CClass)thisClassObject.extra;
//拿到它的类名(.分隔的而不是/) 转成string对象入栈
String clazzName = clazz.getJavaName();
//本地语言字符串包成java的String对象 入栈
OObject stringObject = StringPool.JString(clazz.classLoader,clazzName);
frame.getOperandStack().push(stringObject);
};