`
yeminping
  • 浏览: 180014 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

容易被搞晕的——堆和栈

    博客分类:
  • JAVA
阅读更多

容易被搞晕的——堆和栈

 

    由于“堆”和“栈”这两个概念是看不见摸不着的东西,让很多程序员都整不明白是怎么回事。其实这两个概念也没有什么好研究的,因为堆和栈程序员根本没有办法控制其具体内容。 只需要了解一点,栈与堆都是Java用来在内存中存放数据的地方就行了。然后再弄清楚这两个概念分别对应这程序开发的什么操作,以及堆和栈的区别即可。

 

1 堆——用new建立,垃圾自动回收负责回收

(1) 堆是一个“运行时”数据区,类实例化的对象就是从堆上去分配空间的。

(2) 在堆上分配空间是通过new等指令建立的。

(3) Java针对堆的操作和C++的区别就是,Java不需要在空间不用的时候来显式地释放。

(4) Java的堆是由Java的垃圾回收机制来负责处理的,堆是动态分配内存大小,垃圾收集器可以自动回收不再使用的内存空间。

(5) 缺点是:因为在运行时动态分配内存,所以内存的存取速度较慢。

例如:

String str = new String("abc");

就是在堆上开辟的空间来存放String的对象。

 

2 栈——存放基本数据类型,速度快

(1)栈中主要存放一些基本类型的变量(int、short、 long、byte、float、double、boolean、char)和对象句柄。

(2)栈的存取速度比堆要快。

(3)栈数据可以共享。

(4)栈的数据大小与生存期必须是确定的,缺乏灵活性。

例如:

int a = 3;

就是在栈上开辟的空间来存放int。

 

3 何谓栈的“数据共享”

栈其中的一个特性就是“数据共享”,那什么是“数据共享”呢

这里面所说的数据共享并不是由程序员来控制的,而是JVM来控制的,指的是系统自动处理的方式。比如定义两个变量。

int a = 5;

int b = 5;

这两个变量所指向的栈上的空间地址是同一个,这就是所谓的“数据共享”。

它的工作方式是这样的。

JVM处理int a = 5,首先在栈上创建一个变量为a的引用,然后去查找栈上是否还有5这个值。如果没有找到,那么就将5存放进来,然后将a指向5。接着处理int b = 5,在创建完b的引用后,因为在栈中已有5这个值,便将b直接指向5。

于是,就出现了a与b同时指向5的内存地址的情况。

 

4 实例化对象的两种方法

对于String这个类来说,它可以用两种方法来建立。

String s = new String("asdf");

String s = "asdf";

用这两个形式创建的对象是不同的,第一种是用new()来创建对象的,它是在堆上开辟空间,每调用一次都会在堆上创建一个新的对象。

而第二种的创建方法则是先在栈上创建一个String类的对象引用,然后再去查找栈中有没有存放asdf。如果没有,则将asdf存放进栈,并让str指向asdf;如果已有asdf ,则直接把str指向abc。

在比较两个String是否相等时,一定是用equals()方法,而当测试两个包装类的引用是否指向同一个对象时,应该用“= =”。

因此,可以通过“= =”判断是否相等来验证栈上面的数据共享的问题。

例1:

String s1 = "asdf";

String s2 = "asdf";

System.out.println(s1==s2);

该程序的运行结果是true,那么这说明s1和s2都是指向同一个对象的。

例2:

String s1 =new String ("asdf");

String s2 =new String ("asdf");

System.out.println(s1==s2);

该程序的运行结果是false,这说明用new的方式是生成的对象,每个对象都指向不同的地方。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics