Java进击(五)内存分析

来源:互联网 发布:驱动软件 编辑:程序博客网 时间:2024/06/13 06:44

一、问题--现象

首先看一个问题:

代码段一:

classTesetNeicun{

 public static void main(String[] args){

   String str1="abc";

   String str2 ="abc";

   System.out.println(str1==str2);

 }

}

结果:


代码段二:

classTesetNeicun{

publicstatic void main(String[] args){

Stringstr1 = new String("abc");

Stringstr2=new String("abc");

System.out.println(str1==str2);

}

}


 

二、原因    --解释  

        为什么会出现这种结果呢?我们先看Java中的堆和栈;当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。堆内存用来存放由new创建的对象和数组在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。 

       栈与堆都是Java用来在Ram中存放数据的地方 Java的堆是一个运行时数据区,类的对象从中分配空间堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。  

      栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。栈中主要存放一些基本类型的变量(,int, short, long, byte, float, double, boolean, char)和对象句柄。 

     下面开始分析,代码段一,就是创建两个变量,变量是存在栈中的;代码段二其实java执行的时候是拆解为两条语句执行的:

    String str1; //1

   str1=new String(“abc”); //2

    1. 在栈内存中定义一个名为str1的对String类的对像引用变量;

    2. 在堆内存开辟了一块空间用于存放字符串“abc”,将1定义的引用变量str1指向该空间,其实真正是存在堆中的;str1str2中存的是地址,他们指向不同的两块堆内存空间,所以str1==str2结果为false

  

三、使用

      下面看一个例子,看对象是如何new出来的:

代码:

 

class Cat{privatedouble weight;privateint age;publicCat(double _weight,int _age){  this.weight=_weight;  this.age=_age;}}publicclass CatDemo{ public static void main(String[] args){   Cat kitty =new Cat(3.0,2); }}

      通过代码我们分析,kitty是如何new出来的:(1)先在栈内存中定义引用变量kitty,然后在堆内存中分配一块空间,将kitty猫的属性存放进去;(2)因为Cat有构造函数,我们在new时会在栈内存中定义_weight_age并赋值(3.02),同时在堆中开辟空间,通过构造函数将栈内存中的值附给堆内存中值;(3最后让引用变量指向这个空间over

 

总结:

              栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容;堆中存放使用new关键字创建的对象.

            字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。

            静态成员变量在类装载的时候就进行了创建,在整个程序结束时按序销毁。实例变量在类实例化对象时候创建,在对象销毁的时候销毁。局部变量在局部范围使用时创建,跳出局部范围销毁。


  不足之处,敬请指正,thank you~~~

12 0
原创粉丝点击