在学习java过程中,不知道有没有一些小伙伴在运行代码后,觉得这样的结果跟自己想的不一样,但又不知道究竟为何,比如下面一段小程序
public classTest {public static voidmain(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(intnum){
num= 100;
}//"改变"对象的方法
public static voidchangeObject(Cat c){
c= new Cat("Bule", 3);
}//改变猫年龄的方法
public static voidchangeAge(Cat c){
c.setAge(5);
}
}//猫类
classCat {private String color; //毛色
private int age; //年龄
public Cat(String _color, int_age) {super();color =_color;age =_age;
}
@OverridepublicString toString() {return "Cat [color=" + color + ", age=" + age + "]";
}publicString getColor() {returncolor;
}public voidsetColor(String color) {this.color =color;
}public intgetAge() {returnage;
}public void setAge(intage) {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改变啦啦啦啦。
总结:弄清楚内存进行的情况,能够很好的掌握程序运行过程