您的位置:首页 > 其它

反射(一)------不仅要存储对象的有效数据,还要存储对象的类型信息

2014-12-24 23:17 274 查看
反射,可以允许我们在程序运行期间动态的获取一个类的类型信息,并利用这些信息做一些有用的事情。

要理解反射,首先就要理解Java中的Class对象。我们将尽量抛开复杂的专业术语,用“傻瓜”式的大白话详细介绍Class对象。

我们大家都应该知道,当用new操作符构造一个对象的时候,虚拟机JVM会在内存的heap中分配一块空间用于存储该对象的数据,这块内存空间的大小取决于你要构造对象的类。还有一点我们也应该理解,无论是什么样的程序,在计算机内存中,都是由1和0组成的,因为计算机只认识1和0。

那么问题就来喽!既然在程序运行期间,所有的对象在计算机中都只是一个1、0内存块的话,那么当你调用一个对象的方法或属性的时候,JVM怎么会知道你调用的方法或属性长什么样子?我们来详细描述一下这个场景:有一块固定大小的内存,里面放了一大堆1和0,紧密的排列在一起,JVM怎么会知道哪一段的1、0表示对象的属性A,哪一段的1、0表示对象的属性B呢?还有,对象的方法代码被放在哪里?是每个对象都存储一份方法代码的拷贝吗?还是内存中只保留一份方法代码,然后被所有的对象共享(最后这个问题如果你了解this引用的话,就可以回答了)?

JVM解决上面问题的方式非常简单,当程序运行时,在内存中除了存储对象的有效数据外,还要存储对象的类型信息,也就是要存储对象所属类的信息。看下面例子:

class A
{
int a;
double b;
int c;
}
当构造一个A类的对象时,JVM会在内存中分配一块16字节大小的内存用于存储对象的有效数据。如果这时JVM存储了A类的信息的话,那么JVM就会知道,在这块16字节的内存空间中,开始的4个字节是成员属性a,中间的8个字节是成员属性b,最后的4个字节是成员属性c。这样,一个对象就可以正确被解析了 。

好吧!我承认我这里有点胡扯,上面的这个例子的解释肯定是错误的,因为编译器对一个类的成员属性的先后顺序的排列是根据一定算法的。并不是在源代码中属性靠前,在.class文件中属性就靠前。例如A类的a属性在第一个位置上,但是编译好后的A.class中很有可能b在a的前面。我们这里只是用来说明JVM是根据类的类型信息解析对象内存块的。

OK!说了上面那么一大堆,其实我就是想告诉大家一个事情:当我们在程序中构造了一个对象,不仅要在内存中存储对象的有效数据信息,还要在内存中存储对象所属的类信息。JVM根据对象的类信息,正确解析对象所对应的内存块中的数据。

那么问题又来了,类型信息存储在哪里呢?在程序运行时是如何表示的呢?休息一下再写
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: