a在运行时的内存布局
用一个例子来看看javaVM运行时,类、对象、Class对象、ClassLoader的关系
package demo;
import java.lang.reflect.InvocationTargetException;
public class ClassObjectDemo0 {
/*定义两个具有继承关系的类,两个类内部都为空*/
public static class Person{
}
public static class Coder extends Person{
}
/*哈哈,main函数抛出的异常似乎有点多*/
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InterruptedException{
/*通过对象找到该类的Class对象*/
Coder coder = new Coder();
System.out.println(coder.getClass());
System.out.println("========================");
/*通过Class对象可以看出继承关系*/
System.out.println(Coder.class);
System.out.println(Coder.class.getSuperclass());
System.out.println(Coder.class.getSuperclass().getSuperclass());
System.out.println("========================");
/*查看每个Class对象的类加载器*/
System.out.println(Coder.class.getClassLoader());
System.out.println(Person.class.getClassLoader());
System.out.println(Object.class.getClassLoader());
System.out.println("========================");
/*每个Class对象都是Class类的实例*/
System.out.println(Coder.class.getClass());
System.out.println(Person.class.getClass());
System.out.println(Object.class.getClass());
System.out.println("========================");
/*Class.class的getClass方法会返回它本身*/
System.out.println(Class.class.getClass());
/*产看Class对象的的父类*/
System.out.println(Class.class.getSuperclass());
}
}
运行结果
/*通过对象找到该类的Class对象*/
class demo.ClassObjectDemo$Coder
========================
/*通过Class对象可以看出继承关系*/
class demo.ClassObjectDemo$Coder
class demo.ClassObjectDemo$Person
class java.lang.Object
========================
/*查看每个Class对象的类加载器*/
sun.misc.Launcher$AppClassLoader@4e0e2f2a
sun.misc.Launcher$AppClassLoader@4e0e2f2a
null /*说明Object类的加载器是BootstrapClassLoader*/
========================
/*每个Class对象都是Class类的实例*/
class java.lang.Class
class java.lang.Class
class java.lang.Class
========================
/*Class.class的getClass方法会返回它本身*/
class java.lang.Class
========================
/*查看Class.class对象的父类*/
class java.lang.Object
通过上面的结果,我们可以推测这些对象,方法,加载器等在堆和栈中布局的一种可能。
在堆区中,我们一般的对象我们用浅黄色表示,Class对象用浅蓝色表示(原谅我的辨色能力,什么颜色请自行体会)。
在堆区中,绿色箭头表示getClass方法返回的对象。显然,非Class对象的getClass方法返回这个类对应的Class对象。Class类继承Object类,Object类定义了getClass方法,所有的Class对象也有getClass方法。如果把Class对象看成普通对象,那么它的getClass方法就会返回表示整个Class类的Class对象,即Class.class。而Class.class对象的getClass方法返回它本身。
堆区中,每个Class对象的黑色虚线都指向了方法区中表示该类的全部信息,所以我们能够通过Class对象进行反射操作。
堆区中的黑色实线表示Class对象的getSupperClass方法返回的对象,由于所有的类都继承于Object类,所以有的Class对象最终都指向于Object.clss,而Object.class没有父类。
我们想要实现反射,一般使用Class.forName方法进行类加载,forName方法本质上就是调用ClassLoadr实例的loadClass方法。推测,为了方便每个加载器查找某个类是否已加载器过,每个类加载器可能都有一张表,记录每个已加载的类和对应Class对象的地址。
4.7 数组与Class对象
不同数据类型,不同维度的数组都对应不同的Class对象
所有具有相同元素类型和维数的数组都共享该 Class 对象。
package javalearning;
public class ArrayTest {
public static void main(String[] args){
int[] a1 = new int[10];
int[][] a2 = new int[5][3];
|