对象和引用

来源:互联网 发布:游戏源码是什么 编辑:程序博客网 时间:2024/06/08 05:01
    Student stu=new Student();        Student stu;        stu=new Student();

想理解上面代码的含义,就要知道堆(heap)和栈(stack)的含义

堆(heap)—由new等指令创建的对象和数组,由Java虚拟机的自动垃圾回收来回收不再使用的数据
栈(stack)—基本类型的变量和对象的引用变量,当超过变量的作用域后,Java会自动释放掉该bl,内存空间可以立即被另作他用。

注意: 栈内存储的除了基本类型的变量(int String…)还会存储对象的引用变量,java中,引用变量实际是一个指针,它指向堆内存中的对象实例。

引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。

  • 所以上面代码里的”=”并不是赋值的意思,而是把对象的地址传递给变量
  • 对象创建出来,其实连名字都没有,因此必须通过引用变量来对其进行操作。
        Case cc; //在栈内存里面开辟了空间给引用变量cc,这时cc=null        cc=new Case();          //1. new Case()在堆内存里面开辟了空间给Case类的对象,这个对象名字        //2. Case()随即调用了Case类的构造函数        //3. 把对象的地址在堆内存的地址给引用变量cc
public class ObjectRef {    '''基本类型的参数传递'''    public static void testBasicType(int m) {        System.out.println("m=" + m);//m=50        m = 100;        System.out.println("m=" + m);//m=100    }   '''参数为对象,不改变引用的值'''   '''s即sMain指向的对象执行了append方法,在原来的字符串上加了段“_add”'''    public static void add(StringBuffer s) {        s.append("_add");    }    '''参数为对象,改变引用的值 '''    '''引用变量指向了一个新的对象,已经不是sMain指向的对象了'''    public static void changeRef(StringBuffer s) {        s = new StringBuffer("Java");    }    public static void main(String[] args) {        int i = 50;        testBasicType(i);        System.out.println(i);'''i=50'''        StringBuffer sMain = new StringBuffer("init");        System.out.println("sMain=" + sMain.toString());'''sMain=init'''        add(sMain);        System.out.println("sMain=" + sMain.toString());'''sMain=init_add'''    }}
public class OOTest06 {    public static void main(String[] args) {        int i=10;        method1(i);        System.out.println(i);    }       public static void method1(int temp) {        temp = 1;    }}

以上代码执行过程,首先在栈中创建main方法栈帧,初始化i的值为10,将此栈帧压入栈,接着调用method1()方法,通常是在栈区创建新的栈帧,并赋值temp为1,压入栈中,两栈帧都是独立的,他们之间的值是不能互访的。然后method1()方法栈帧弹出,接下来执行输出i值的语句,因传递的是值,所以不会改变i的值,输出结果i的值仍然为10,最后将main方法栈帧弹出,main方法执行完毕。
结论:只要是基本类型,传递过去的都是值

public class OOTest07 {    public static void main(String[] args) {        //创建一个对象        Student student = new Student();        student.id = 1001;        student.name = "张三";        student.sex = true;        student.address = "北京";        student.age = 20;        method1(student);        System.out.println("id=" + student.id);             System.out.println("name=" + student.name);        System.out.println("sex=" + student.sex);        System.out.println("address=" + student.address);        System.out.println("age=" + student.age);    }       public static void method1(Student temp) {        temp.name="李四";     }}class Student {    //学号    int id;     //姓名    String name;    //性别    boolean sex;    //地址    String address;    //年龄    int age;}

程序执行流程
1. 执行main方法时,会在栈中创建main方法的栈帧,将局部变量student引用保存到栈中
2.将Student对象放到堆区中,并赋值
3.调用method1方法,创建method1方法栈帧
4.将局部变量student引用(也就是student对象的地址),传递到method1方法中,并赋值给temp
5.此时temp和student引用指向的都是一个对象
6.当method1方法中将name属性改为“李四”时,改的是堆中的属性
7.所以会影响输出结果,最后的输出结果为:李四
8.main方法执行结束,此时的student对象还在堆中,我们无法使用了,那么他就变成了“垃圾对象”,java的垃圾收集器会在某个时刻,将其清除,以上就是地址传递,也就是引用的传递
结论:除了基本类型外都是地址传递

将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方                                    ---引用《Java编程思想》
原创粉丝点击