刚刚写了对于面向对象思想的理解,回家后想起来今天还有一个很重要的东西没有写,就是对类占用内存空间的分析,之前博客记载了对数组占用内存空间的分析,今天说一下类在内存中的占用情况。
可能是因为之前没有真正理解编程语言中占用内存的各种情况,所以现在一旦遇到这种分析,我就想把它记录下来,以防下次不记得的时候可以回顾一下。
其实和数组一样,创建一个对象就是采用这样的格式 类名 对象名=new 类名() 来创建一个新的对象,这就和新建一个数组是一样的,在栈中申请一个内存空间记录下数组名这儿是类名,然后后面new就是在堆中申请一块内存空间,并将这一块内存空间的地址给栈中的对象名,那么它们就连接起来了。但是,和数组不一样的是,类占用内存还涉及到方法区这一个存储空间,比如java程序后编译的.class文件是存储在方法区中的,方法区中记录了这个类的成员变量和成员方法。当类在堆中申请内存空间时,会将这个类在堆中存放的地址和没有被static修饰的成员变量一起给堆内存。那么就可以通过堆中的地址指向这一块方法区了(blog.kgraph.cn)。
单纯是用文字是很难记录的,具体看下图:
类原理图片解析

左面是我写的一个调用学生类的包含main方法的类,其中学生类没有给出,学生类的代码如下:
学生类的代码
class Student{
public String name;//学生姓名
public String sex; //学生的性别
public int age; //学生的年龄
//学生类中的上课的课程
public void study(String className){
System.out.println(“学生正在上”+className);
}
//学生类中的玩游戏的方法
public void playGame(String gameName){
System.out.println(“学生正在打”+gameName);
}
//学生类中的吃饭的方法
public void eatFood(String foodName){
System.out.println(“学生正在吃”+foodName);
}
学生类中包含三个成员变量,都没有用static修饰,分别是name、sex、age,成员方法是study(),playGame(),eatFood()。在图片上的程序是先new了一个Student类的s,所以会在栈内存中申请如图所示的一块空间,并且在堆内存中也申请了一块空间,并且将堆中这一块的地址0x0001给了栈中的s,那么栈中的s就可以指向0x0001这个地址的堆内存了,看图上,方法区中存储的是StudentDemo.class和Student.class文件的成员变量和成员方法,当创建学生类s时,会将方法区中student类中没有被static修饰的name、sex、age和方法区的地址给堆内存中对应位置,并且它们都有初值,基本数据类型的值都是其默认值,引用数据类型是null,当程序继续进行的时候,程序根据已经建好的连接分别给s的成员变量分别附上了值,后面对Student类s1的赋值也是这样,紧接着,调用s.study()方法时,是根据s中的地址找到堆内存然后根据堆内存中的0x0002找到方法区,然后找到study()这个方法,值得注意的是java虚拟机会在栈中申请一块内存空间将study()方法的代码块压入这块内存实现s.study(“JavaSE”),在执行完这段代码后,会断开连接,等待垃圾回收机制空闲的时候来回收这块内存空间,同理后面的也是这样。当创建s3对象的时候,并没有在堆中申请内存空间,而是将s指向的那块内存空间的地址给了s3,那么和之前的数组一样,它们同时指向了0x0001这一块堆内存。当对s3的各项成员变量进行赋值的时候,再次输出s的name、sex、age时候就已经变成更改后的内容了。
希望以后再遇到类似的思想可以轻而易举的想到。