java this关键 内存_JAVA-初步认识-第七章-this关键字内存图解

一.

对于静态的使用和注意事项已经讲解过了,接下来用一个例子,把静态所涉及的内存区域用图的形式给大家展现一下。

d61485cc02fddc207aaf10eb08a3d8da.png

这里面进行了一个Person的描述,里面有两个成员变量name,age,同时有一个静态的变量country。接下来Person当中给我们提供了一个构造函数,能同时初始化性能和年龄。接下来还有一个非静态的方法show,可以显示出这个人的个人信息。接下来还有一个静态方法,它可以去显示我们国籍。

主函数中我们先用类名的形式调用了静态方法,紧接着创建了该类的对象,该类的对象调用了一个非静态的方法,这个方法只能被静态调用。

上面的例子中,主函数里面的语句Person p=new Person(); 这里显示括号里没有任何参数。在描述类中,没有空参数的构造函数,这里也就无法进行构造函数初始化。

b80c6b8949ea2e0a809f65416d13e8d4.png

以上面的描述为例,来将内存中的过程展现一下。(我觉着这里还是想将学到现在的所有面向对象知识点串起来,理清先后顺序。)

09ad5abf853550774e77acba1f773313.png

上面的截图内容挺不同寻常的,没有进行编译StaticDemo2的源程序,而是直接用java命令运行了StsticDemo2的类。就是说,没有编译就运行了?

这是在运行一个类,这个类就会被加载进内存,至于这个类被封装对象的过程,现在讲不了。这个部分到后面才能讲到。一加载进来就要进行空间的开辟。

无论怎样,计算机内存早就被划分为几个部分,来分别存储不同的东西。目前涉及的内存区域主要有三个,栈,堆,方法区。

区域划分完毕后,数据都在哪?是个问题。

方法存在哪?方法都存放在方法区里。解析一下,方法是如何在方法区存放的。

当StaticDemo2这个类被执行的时候,其实这个类就进内存了(程序运行都是在内存中操作的)。这个类一进内存,就开辟空间了。

03804f124d574e2c3d3046ebe56388ba.png

在方法区划分了一片空间,存储StaticDemo2的类,分完以后,这个类里面有一个成员方法,就是StaticDemo2(),这个方法搞不清楚是哪来的?这个方法是这个类中的默认构造函数。会随着类一起加载进来。

主函数是静态的,main()会被加载入静态区,专门存储静态的数据。静态区里也会标明是StaticDemo2的类,然后里面有static main()的方法。

上面一左一右,左边是非静态区,右边是静态区。非静态区的方法和静态区的方法都是被共享的。为什么?以描述类中的show()方法而言,所有的对象都具备这功能,唯一的不同是什么?就是对象所封装的数据不一样。有的对象叫张三,有的对象就李四,但是大家都会说话,都会说的自己姓名和年龄,所以这个功能是共享的,这个功能就在方法区里面。只不过方法区分静态和非静态,因为调用方式和所属的不一样。非静态区域里面所有的成员都有一个this所属。为什么?非静态的内容只能被对象调用。而到了静态区,它有都有所属的类名。

7ca7593269072932ca31e8fa1cad8975.png

在控制台上,将java StaticDemo2一回车,它就加载完了。加载完了,虚拟机就直接使用这个类名,调用方法。这个时候,main方法就进栈。main方法进栈以后,它就要运行里面内容,但是main方法里面的代码是存储在静态区。因为,源程序中的所有东西都被转换成了字节码文件存储起来了。mian本身就在静态区,它的代码也在静态区。

5b62a80e054f95e30b869839a14264d0.png

第一句Person.show()使用到了一个类,这个时候,这个类才加载。这个时候就去找,classpath路径下是否有Person.class文件。如果没有设置classpath,它就默认在当前目录下找,找到以后,就会把person.class文件加载进内存。一加载就会在方法区,分配空间了。Person类就进内存了,紧跟着Person的构造函数,以及show方法。它们加载完以后,static method的方法也会加载进来,这个方法所属Person类。这是我们所说的静态区,都是共享数据。紧接着,这里面还没完,里面还有country,country默认初始化为null,接着初始化为"CN",

80fba44b9f96e8752a4dbca164ff4076.png 

7f0a4e8cad83936095e8f635655d1d94.png

加载完以后,是Person.method(),是类名在调用。用类名调用,只能找静态区。到静态区一找,在Person这个类所属的静态区当中或者说在静态区当中有Person类,Person类区域当中,有没有main方法呢?有的话,method的方法就进栈了。这个方法持有this么?没有,只有非静态区的才有this。到目前为止,堆里面没有东西。注意,method的方法从方法区里的静态区,到了栈内存中。下面的右截图的虚线是代码存放区,有的也叫做方法表。栈中的method是运行区,里面会有局部变量,运行完释放。栈区中存放方法的局部变量,System.out.println是不进来的,

1b54c6ee2679b0e8cfa594c8e6bc89d0.png 

af4badeb0bc7606a088140321b0dfe32.png

69c7dc5e2fd3360e987f7d8ba40cc344.png

方法进栈完以后,它就开始运行,运行的时候,就开始执行方法行动代码。有变量就开辟空间,没变量空间开辟完以后就会释放。一运行,Person.country就输出了,它在调用country这个一个变量。发现这个变量是类名.,如果不写类名.的话,class文件里也有。调用的时候,是找person里静态变量,一找到,就把CN给输出了。输出完以后,再往下就是return;method方法就弹栈了,到这呢,这个方法区就加载完毕了。

25891cd184050afad948162c9d748c45.png

接着就执行第二句,Person p=new Person("java", 20); 接着主函数里面就多了个p,=右边是一个Person。堆内存中就开辟空间,分配地址编号,加载成员变量,默认初始化值。当然在类的描述当中,它可以描述描述自己的name和age,但是存在类型被使用,必须存到对象当中,因为这个name和age值是只能在对象中存在的。默认初始化完毕后,要接着构造函数初始化。这时,就要回头找,相对应的构造函数。这个时候,构造函数就进栈了,而这个构造函数在访问对象中的数据,它在给对象中的数据进行初始化。给哪个对象初始化呢?它不知道,所以它里面就持有一个this,而这时正好是0x0056的对象在调用构造函数,所以this等于0x0056. 紧跟着它的name就被赋值为”java“,age就被赋值为”20“,。紧跟着,这个函数完事以后,开始执行,构造函数里面的代码,this.name=name, this.age=age,一致性时,发现构造函数里面的name赋值给this.name,而this是0x0056的对象,也就是name=”java“赋值给了对象中的name。

e7574978b47235c3dbfa1c98f8f8fd81.png 

85b3e3520914bce510921174d2ad09a5.png 

ae3019e002715f4c77884cd293786e5f.png

25f516ce89b31e7bebf74aa491641bc7.png

这时候,构造函数就完毕了,它就要弹栈了。紧跟着,右边堆中的对象初始化就结束了。接着就把地址编号0x0056赋值给左边p,这样一来,p就指向了对象。

f82a3331932f8e3051810154ab7db924.png

最后,执行p.show(),调用show方法。在方法区的非静态区有show方法。注意:在p.show在编译的时候,它会检查的源文件是否有show,没有的话,就编译失败了。可是运行的时候,它也会检查,发现有show,就让show进栈。show是非静态的,show得有this所属0x0056,执行里面代码,发现没有局部变量,只有输出语句。就直接执行输出语句。在输出的时候,发现输出country,大家都知道在counrty在编译完以后,在生成class文件,就已经有类名所属,所以它就找静态区里面的内容。找完以后,就打印了CN。接着找寻name和age的值,name和age前面有this,打印的都是0x0056的值,指向对象中的name和age值。找到以后,就输出了,CN,java,20.输出完以后,show方法就弹栈。

3cb957a4d55c99d8ab38494cb327f451.png

它弹栈以后,主函数的最后一句话就是return,这是默认,隐式,写不写都可以,系统会自动帮你加上,函数要结束。构造函数有return语句,一般方法有return语句。只有void的情况,return才可以省略。主函数有renturn,也弹栈。接着没有代码了,虚拟机结束了。这里面涉及线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值