一、前提:
最近在学习马士兵J2SE视频教程,其中第三章面向对象中涉及到了内存管理,马老师多次强调,谁掌握了内存,谁就理解了一起。由此可见,内存管理的重要性。在此做一些总结。本人纯属小白,还望大神多多指导。
先介绍一下Java的一些基本概念: 首先是成员变量:成员变量可以是Java语言中任何一种数据类型(包括基本类型和引用类型);在定义成员变量时可以对其初始化;成员变量的作用范围是整个类体。
引用: Java语言汇总除基础类型(int、float、bool等)之外的变量类型都称之为引用类型,Java中的对象是通过引用对其操作的。如果不对引用类型的成员变量进行初始化,则默认为null。引用类型占两块内存,而基础类型占一块内存。
二、内存管理:
1、如何在内存中区分类和对象?
类是静态的概念,代码区对象是new出来的,位于堆内存,类的每个成员变量在不同的对象中都有不同的值(静态变量除外),而方法只有一份,执行的时候才调用。
2、在内存管理中,一般将内存分为四个区:栈区、堆区、代码区、数据区、
①栈区(Stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等。
②堆区(heap):一般由程序员释放,或由垃圾回收机制自动回收。new申请的内存位于此区,new出来的东西放在此区(new出来的是对象)。
③全局区(静态区)(Static):全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。
④文字常量区:常量字符串就是放在这里。程序结束后由系统释放。
⑤代码区:代码区也叫方法区。存放函数体的二进制代码。
三、举例说明:
1、代码如下:
<span style="font-family:KaiTi_GB2312;font-size:24px;">class BirthDate {
private int day;
private int month;
private int year;
public BirthDate(int d, int m, int y) {
day = d;
month = m;
year = y;
}
public void setDay(int d) {
day = d;
}
public void setMonth(int m) {
month = m;
}
public void setYear(int y) {
year = y;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
public void display() {
System.out.println
(day + " - " + month + " - " + year);
}
}
public class Test{
public static void main(String args[]){
Test test = new Test();
int date = 9;
BirthDate d1= new BirthDate(7,7,1970);
BirthDate d2= new BirthDate(1,1,2000);
test.change1(date);
test.change2(d1);
test.change3(d2);
System.out.println("date=" + date);
d1.display();
d2.display();
}
public void change1(int i){
i = 1234;
}
public void change2(BirthDate b) {
b = new BirthDate(22,2,2004);
}
public void change3(BirthDate b) {
b.setDay(22);
}
}
</span>
当我们分析程序时,我们应该从main方法的第一句话开始分析。在本例中为Test test = new Test();是调用了构造方法。此时内存如下:
第二句话:int date = 9,在栈区中开辟一块内存。存放变量date,初始值为9。第三句话 BirthDate d1= new BirthDate(7,7,1970),都调用了BirthDate()方法。它有三个形参,需要在栈区中分配三块内存。此时内存如下:
当调用方法完毕之后,为这个方法分配的所有的局部变量自动消失。此时内存的布局如下图所示。d2的过程也是如此。详细过程不再展示。
当执行 test.change1(date)语句时,需要调用 change1方法,当方法开始执行时,需要为参数i分配内存空间。此时内存如下,同理方法结束之后,i的空间自动消失。
当执行test.change2(d1)的时候,又需要在栈中分配出一个一个局部变量b,在堆中分配一块区域。方法执行完毕后,局部变量b消失。在某一个时间,垃圾收集机制会回收刚刚分配的堆区。(一般没有引用指向它的时候,垃圾收集机制会回收它)。
当执行test.change3(d2)方法完成后,此时内存布局如下。
四、总结:
一定要把内存的执行过程弄懂,整个程序执行的过程将非常明白。关于程序执行过程中内存变化还有好多需要研究的。本文仅仅是起到抛砖引玉的作用。