java内存解析
在学习java过程中,不知道有没有一些小伙伴在运行代码后,觉得这样的结果跟自己想的不一样,但又不知道究竟为何,比如下面一段小程序
public class Test { public static void main(String[] args) { int i = 1; Cat c1 = new Cat("Black", 1); Cat c2 = new Cat("Yellow", 2); changeNum(i); changeObject(c1); changeAge(c2); System.out.println("i=" + i + ", c1=" + c1 + ", c2=" + c2); } //"改变"数值的方法 public static void changeNum(int num){ num = 100; } //"改变"对象的方法 public static void changeObject(Cat c){ c = new Cat("Bule", 3); } //改变猫年龄的方法 public static void changeAge(Cat c){ c.setAge(5); } } //猫类 class Cat { private String color; //毛色 private int age; //年龄 public Cat(String _color, int _age) { super(); color = _color; age = _age; } @Override public String toString() { return "Cat [color=" + color + ", age=" + age + "]"; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
看到运行结果,有些人也许会疑惑i的值和c1为什么并没有改变,只有c2改变了
其实只要我们弄明白java程序在运行过程中的内存情况,就会明白啦。首先,了解一下内存中存放情况
在执行main方法时,在栈内存中会有三个局部变量:i,c1和c2;在堆内存中会有两个new出来的猫对象,如下:
其实当在new出猫的实例时,调用了Cat的构造方法,哪cat1来说,在栈(stack)中分配成员变量color和age;在调用时,分配构造方法的参数变量(形参)并赋值_color=“balck”和_age=1.然后将值分别赋值给color和age。构造方法运行结束,其成员变量全部消失,最终情况即上图所示。
接下来执行changeNum(i);执行过程为:在栈中分配该方法的形参int num;然后将i的值赋予num,即num=1;然后执行方法体,num=100;其实这时候只是num的值改变了,i的值并没有变化,最后方法执行结束,num消失。(下图)
执行方法changeObject(c1)时,同样在栈中分配引用变量(形参)c,并且指向c1对象;执行方法体时,现在堆(heap)中new出一个新对象(“Blue”,3),然后指向了这个新的对象,所以,真正改变的知识c而非c1;方法执行结束,c消失,新的对象没有任何变量指向它,随之也会在合适的时间被垃圾回收期回收。(下图)
最后执行方法changeAge(c2),同样在栈中分配引用变量(形参)c,并且指向c2对象,执行方法体c.setAge(5);将堆内存中的对象age改成了5,最后结束消失,c2仍指向该对象,所以c2改变啦啦啦啦。
总结:弄清楚内存进行的情况,能够很好的掌握程序运行过程