修改文,参考文献:http://www.jb51.net/article/108751.htm
Java把内存常用为两种:一种是栈内存,另一种是堆内存。
栈内存:用来存放基本类型的变量和对象的引用变量。当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量分配的内存空间,该内存空间可以立即另做他用。(比如,函数A调用函数B,函数B中定义变量a。变量a的作用域只是函数B,在函数B运行以后,变量a会自动被销毁,分配给它的内存会被回收。后面将会通过图片详细说明)。
堆内存:用来存放由new创建的内存数组和对象。在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理。在堆中产生一个数组或对象之后,可以在栈中定义一个特殊的变量,让栈中的这个变量值等于在堆内存中的数组或对象的首地址,栈中的这个变量就变成了数组或对象的引用变量,以后就可以在程序中使用引用变量来访问堆中的数组或对象。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其他作用域之外后边释放。而数组和对象在堆中分配,即使程序运行到使用new产生的数组或者对象的语句所在的代码块之外,数组和对象所占据的内存不会被释放。数组和对象在没有引用变量指向它的时候,才变为垃圾,不能再被使用,在随后的一个不确定时间被垃圾回收器收走(释放掉),这也是Java比较占内存的原因。
实际上,栈中的变量指向堆内存中的变量,就是Java中的指针。
对象在堆内存空间的首访问地址(对象可能是数组),而对象的具体属性,例如name和sex等在对象被实例化时才被保存在堆内存中。(Ps:倘若我们只实例化对象,而没有赋值,JVM依旧会为为该对象开辟一块堆内存存储该对象,只不过对象属性为null或0,例如:Person Person3 = new Person())。
上述第一步,对象Stu1进行了实例化,JVM为其开辟了一块堆内存空间,但并没有赋值;而对象Stu2仅仅只进行了声明操作,而没有进行实例化操作,所以在第一步时,Stu1是个引用变量,Stu2还只是个普通变量。
第二步,应用变量Stu1赋值给了Stu2,所以Stu2的指针指向Stu1成为了一个引用变量,两者共同指向相同的堆内存地址,共享里面的数据。
第三步,为对象Stu1赋值,由于Stu2指针指向Stu1,所以Stu2也可以获取堆内存赋值之后的数据。
第四步,同理,由于两对象指向共同堆内存地址,所以无论哪一方的对象属性被修改,结果都会发生改变,应为对它们而言数据是共享的。
从上面可以看出,基本类型的对象和空的对象引用变量之间的比较是直接比较的,而对象虽然属性相同,但是比较结果并非为true,这是因为对象在栈中的存储地址不相同,所以该对象非此对象。(长的非常像的双胞胎,你能说是同一个人吗?)
从上述图中可以看出,一个栈内存只能指向一个堆内存空间,如果要想指向其他堆内存空间,则必须先断开已有的指向,才能分配新的指向。Java本身提供垃圾收集机制(Garbage Collection,GC),会不定期释放不用的内存空间,只要对象不用了,就会等待GC释放空间,如上面堆内存中的name="Rao"、age=22
int和Integer的区别,long和Long等同理
1、Integer是int的包装类,int则是java的一种基本数据类型 2、Integer变量必须实例化后才能使用,而int变量不需要 3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 4、Integer的默认值是null,int的默认值是0
int和Integer的比较,long和Long等同理
1、由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。
Integer i = new Integer(100); Integer j = new Integer(100); System.out.print(i == j); //false
2、Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
Integer i = new Integer(100);
int j = 100; System.out.print(i == j) //true
3、非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer i = new Integer(100); Integer j = 100; System.out.print(i == j); //false
4、对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100;
Integer j = 100; System.out.print(i == j); //true
Integer i = 128;
Integer j = 128; System.out.print(i == j); //false
关于Java内存分配机制的详解到这里也就结束 ,该文章主要是前面两位前辈的整合版,稍有修改。
------ END ------