人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中?

这里浅谈Java中的栈和堆

首先,将结论写在前面,后面再用例子加以验证。

Java的栈中存储以下类型数据,栈对应的英文单词是Stack

基本类型

引用类型变量

方法

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

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

栈有一个很重要的特殊性,就是存在栈中的数据可以共享。

Java的堆中存储以下类型数据,堆对应的英文单词是Heap

实例对象

在函数中定义的一些基本类型的变量(8种)和对象的引用变量都是在函数的栈Stack内存中分配。当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆Heap内存用于存放由new创建的对象和数组。在堆中分配的内存,由java虚拟机自动垃圾回收器来管理。在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量,这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象,引用变量相当于为数组或者对象起的一个别名,或者代号。

引用变量是普通变量,定义时在栈中分配内存,引用变量在程序运行到作用域外释放。而数组&对象本身在堆中分配,即使程序运行到使用new产生数组和对象的语句所在地代码块之外,数组和对象本身占用的堆内存也不会被释放,数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因,实际上,栈中的变量指向堆内存中的变量,这就是 Java 中的指针!

class Person {

    int age;

}

public class LearnHeap {

    public static void main(String args[]){

        int a=10;
Person person = new Person();
person.age =20; change(a,person);
System.out.println("a="+ a+",and person.age = "+person.age); } static void change(int a1, Person person){ a1 = 11;
person.age= 21;
System.out.println("a1="+ a1+",and age1 = "+person); } }

  两次的输出结果是什么?猜测下。

以上程序内存加载的执行步骤:

第1步 —— main()函数是程序入口,JVM先执行,首先将main方法压入栈中,在栈内存中开辟一个空间,存放int类型变量a,同时附值10。
      在堆中分配一片区域,用来存放和创建Person对象,这片内存区域会有属于自己的内存地址,假设是1001,然后给成员变量赋值,age=20
      执行结束后,构造防范弾栈,Person创建完成,将Person的内存地址1001赋值给person(此处person小写,是引用变量类型)

第2步 —— JVM执行change()函数,在栈内存中又开辟一个新的空间,存放int类型变量a和对象Person中person
     此时main空间与change空间并存,同时运行,互不影响。

第3步 —— change()方法执行,将a赋值为11,person对象的堆中年龄age赋值为21

第4步 —— change()执行完毕,变量a立即释放,空间消失。但是main()函数空间仍存在,main中的变量a仍然存在,不受影响。而person在堆中对应的地址,所指的age已经赋值=21

实际输出如下:

结论:

如果a()方法中的基本类型(8个)变量x传入b()方法中,并在b()中进行了修改,则a()方法中的x的值保持不变 
如果a()方法中的引用类型        变量x传入b()方法中,并在b()中进行了修改,则a()方法中的x的值与b()保持一致

下面对8中基本类型进行简单的测试

package heapandStack;

public class LearnHeap02 {

    public static void main(String args[]){

        byte b=10;
short s=20;
int i=30;
long l =40l; float f =12.34f;
double d = 100.123d; char c = 'A';
boolean flag = true; change(b,s,i,l,f,d,c,flag); System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l); System.out.println(f);
System.out.println(d);
System.out.println(c);
System.out.println(flag); } static void change(byte a, short b, int c,long d, float f, double g, char h,boolean x){ a =11;
b=21;
c =31;
d =41l;
f=12.99f;
g= 200.123d;
h ='V';
x =false; System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d); System.out.println(f);
System.out.println(g);
System.out.println(h);
System.out.println(x); }
}

  

下面测试一下数组,是不是属于实例对象类型

public class LearnHeap03 {

    public static void main(String args[]){

     int a[] ={1,2,3};
change(a);
for(int i:a)
System.out.print(i+" "); } static void change(int[] a){
a[0]=4;
a[1]=5;
for(int i:a)
System.out.print(i+" ");
System.out.println("============ "); }
}

  从结果看出,数组的值被改变了

Java种8种基本数据类型,并不包含String,String的值会被change函数改变吗?String应该存在栈中,还是堆中呢?

先直接上测试代码

public class Learn04 {

    public static void main(String args[]){

        String s1 = new String("abcd");
String s2 = "asdfghjkl";
System.out.println(s1+", "+s2);
change(s1,s2);
System.out.println(s1+", "+s2); } static void change(String s1,String s2){
s1 ="123456";
s2 ="000000";
System.out.println(s1+", "+s2); }
}

两种的形式来创建String,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。 而第二种是先在栈中创建一个对String类的对象引用变量s2,然后查找栈中有没有存放"asdfghjkl",如果没有,则将"asdfghjkl"存放进栈,并令str指 向”abc”,如果已经有”asdfghjkl” 则直接令s2指向“asdfghjkl”。  

 

既然讲到两种形式创建String,下面讲一个String两种形式创建的区别,先看一段代码

public class Learn05 {

    public static void main(String args[]){

        String s1 = new String("abcd");
String s2 = "abcd";
boolean a =s1.equals(s2);
boolean b =(s1==s2); System.out.println(a);
System.out.println(b); String s3 = "abcd";
boolean a1 =s3.equals(s2);
boolean b1 =(s3==s2); System.out.println(a1);
System.out.println(b1); } }

  

浅谈Java中的栈和堆的更多相关文章

  1. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  2. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  3. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

  4. 浅谈Java中的对象和对象引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  5. 浅谈Java中的equals和==(转)

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...

  6. 浅谈Java中的equals和==

    浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...

  7. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

  8. 浅谈Java中的final关键字

    浅谈Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...

  9. 【转】浅谈Java中的hashcode方法

    哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native int hashCode(); 根据这个 ...

随机推荐

  1. 监控MySQL主从脚本

    示例一: cat check_mysql_health #!/bin/sh slave_is=($(mysql -S /tmp/mysql3307.sock -uroot -e "show ...

  2. 每日linux命令学习-grep模式检索

    grep模式检索指令包括grep,egrep,和fgrep,.Linux系统使用正则表达式优化文本检索,所以在此,笔者首先学习了一下正则表达式. 1. 正则表达式 正则表达式使用被称为元字符(Meta ...

  3. ucos ii 46个系统API函数解析

    源: ucos ii 46个系统API函数解析

  4. 01:saltstack 基本使用

    1.1 准备实验环境: 安装系统 1)硬件配置如下 2) 先把光标放到”install CentOS 7”,按 Tab键编辑内核参数,添加 (net.ifnames=0 biosdevname=0) ...

  5. mvc 文件下载

    public class DownLoadHelper { /// <summary> /// WriteFile实现下载--测试通过 /// </summary> /// & ...

  6. AnswerOpenCV(0826-0901)一周佳作欣赏

    1.OpenCV to detect how missing tooth in equipment Hello everyone. I am just starting with OpenCV and ...

  7. Codeforces Round #439 (Div. 2) Problem B (Codeforces 869B)

    Even if the world is full of counterfeits, I still regard it as wonderful. Pile up herbs and incense ...

  8. QML获取随机颜色

    rect.color =);//random返回0~1的随机数

  9. 创建一个maven项目

    创建父工程 1.新建maven project,点击next 2.默认配置,点击next 3.默认配置,点击next 4.填写Group Id一般采用域名倒写,Artifact Id为项目名称.然后点 ...

  10. 碎碎念android eMMC【转】

    本文转载自:https://blog.csdn.net/Fybon/article/details/44242549 一./dev/blockroot@:/dev/block #ls bootdevi ...