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改变啦啦啦啦。

总结:弄清楚内存进行的情况,能够很好的掌握程序运行过程

posted @ 2017-03-09 20:59  Stitch_wyq  阅读(419)  评论(0编辑  收藏  举报