上一篇在介绍java虚拟机之前,我们谈到了什么是java的基本类型和引用类型,平时我们应该注意的东西,然后我们谈到了java虚拟机中的堆和栈,但是也只是很简单的说了一说,但是我觉得在java中最重要的就是理解好堆和栈,因为java的面向对象特性我觉得跟堆和栈的分离密切相关,所以就仔细深入的谈谈。
1.我不知道有没有人会疑惑,为什么java要把堆和栈分开呢?堆能存储东西,难道栈就不能了吗?在运行的时候不就是把数据放在栈中吗?
(1)是的,确实是这样的,正如之前所说的栈是负责运行时的,而堆是负责存储信息的。不知道大家有没有了解设计模式里面的一些原则,其中有一条的为对象之间的松耦合而努力,在用在这里同样适用,把栈和堆分离开来,可以使处理逻辑的条理更加清晰,这种原则我觉得在设计软件的时候要注重,套用一个词就是分而治之,后面讲到的垃圾回收是不是就变得可行了呢?。
(2)从线程共享的方面来看,堆和栈的分离,可以使堆的信息是线程共享(或者说是栈共享的)的,这样就为多线程同时访问一个对象提供了可能。而这样方式对于数据交互是有效的(通过共享内存),而且堆中的共享常量和缓存可以给多个栈访问,节约了空间。
(3)套用某个大神的话来说,面向对象就是栈和堆的完美结合。这个怎么理解会比较好呢?认真的想一想,我们平时一般创建一个对象是不是就是把事物的特征抽象出来,但是调用方法呢?是不是就是相当于处理一个个的逻辑,既然是逻辑是不是就是跟栈密切相关?所以说面向对象的实现跟堆和栈的结合是分不开的。
2.我们还需要重点记住的就是,在java中程序的入口一定是Main函数, 也就是栈的起点,因为我们都是在栈中处理逻辑的。
3.接下来,我们就要想一想了,到底堆中存的是什么?栈中存的是什么?
对于堆中要存的数据,我觉得大家闭着眼都会,不就是一个个的对象吗?那么栈中存的是什么呢?其实也很简单,那就是上一篇我们重点讲的基本数据类型,以及对堆中对象的引用,这样来说是不是就清晰了一点。
4.Java中的参数传递时传值呢?还是传引用?
(1)如果要理解这个,我觉得需要明白的一点是,在java中是没有指针这个概念的,但是不要认为java中就没有使用到指针。
(2)java的程序是在栈中运行的,在传递参数的时候,栈中只存在传基本类型和对对象的引用的问题,并没有传对象的本身。
明白了上面的两个原则,我觉得上面的问题就不难解答了,但是我们还需要注意的一点就是,传递的参数如果是基本类型的话,就不能够更改他的值,如果传的是对象的引用,我们可以改变对象里面的属性,成员变量等。换而成一句话就是一个基本类型不能改变,但是有很多个基本类型组成的对象确实可以修改。
最后用一句话来总结,在java程序中,可以没有堆,但是不能没有栈,至于为什么我觉得可以思考一下,什么是程序的入口。