知道美河 | 上传资料 | VIP申请 | 精品课程 | 资料搜索 | 问题反馈 | 会员手册 | 积分消费 | 积分充值 | 帐号保护
美河学习学习在线赞助VIP

美河学习在线(主站) eimhe.com

 找回密码
 建立账号
查看: 6232|回复: 2

[转帖] JAVA经典问题:传值还是传引用

[复制链接]
发表于 2007-10-3 17:44:20 | 显示全部楼层 |阅读模式
public class TestRef {

   

    public static void main(String[] args)

    {

        ValueObject vo1 = new ValueObject("A", 1);

        System.out.println("after vo1: " + vo1.getName()); //=A

        

        changeValue1(vo1);

        System.out.println("after changeValue1: " + vo1.getName());

                //=A1, changed

        

        changeValue2(vo1);

        System.out.println("after changeValue2: " + vo1.getName());

                //=A1, changeValue2内部的赋值不会影响这里。

    }



    /**

     * 使用vo1自身的函数对其内部数据进行改变是有效的,函数外可反映出来

     * 这种object称为可变的(mutable)

     * @param vo1

     */

    private static void changeValue1(ValueObject vo1) {

        vo1.setName("A1");

    }



    /**

     * 在函数内给vo1重新赋值不会改变函数外的原始值

     * @param vo1

     */

    private static void changeValue2(ValueObject vo1) {

        vo1 = new ValueObject("B", 2);

        System.out.println("inside changeValue2: "+ vo1.getName());

                //=B,赋值操作引起的结果变化仅在changeValue2内部有效

    }

}



class ValueObject {

   

    public ValueObject() {}

   

    public ValueObject(String name, int id)

    {

        this.name = name;

        this.id = id;

    }

   

    private String name;

    private int id;

    public int getId() {

        return id;

    }

    public void setId(int id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

}



解释,vo1作为一个object,当它被用作函数参数的时候传递给函数的是一个引用值,这个名称有点怪,又有引用又有值,到底是引用还是值呢,就看你怎么理解了。如果你是去考试,官方的答案是值。可是看起来又象引用啊,希望从这个例子,你能理解java参数传递和和C/C++程序中的引用传递的不同的地方。另外,这也是java作为OO语言的特性之一:封装的体现。

先讲一下对象赋值的关系,举例来说,下列代码:

ValueObject v2, v3;
v2 = new ValueObject("C", 3); 粗体的部分创建了一个数据结构,假设存放在内存地址A000,赋值给句柄 v2
v3 = new ValueObject("D", 4); 粗体的部分创建了一个数据结构,假设存放在内存地址B000,赋值给句柄 v3
v2 = v3; 这句话的作用是把操作B000的地址的句柄的值付给了v2的句柄,使得v2和v3一样操作B000的地址,这意味着:
1.原来v2指向的地址A000变成无主的内存地址,将自动被jvm回收。
2.既然v2和v3指向同一片地址,对v3的修改v2也能得到,反之亦然。

整理得下列代码,请感兴趣的朋友运行验证
ValueObject v2 = new ValueObject("C", 3);
ValueObject v3 = new ValueObject("D", 4);
v2 = v3;
System.out.println("after v2=v3");
System.out.println("v2= "+ v2.getName());//=D
System.out.println("v3= "+ v3.getName());//=D
v3.setName("C1");
System.out.println("after v3 setnameTo C1");
System.out.println("vo2= "+ v2.getName());//=C1
System.out.println("vo3= "+ v3.getName());//=C1

因此,可以得出结论,java中对象的每个实例(instance, 比如vo1, v2, v3 都是ValueObject的实例)的内存地址是唯一的,它一旦被创建,能够对这个地址进行操作的就是每个实例自己,如果ValueObject类中没有public void setName之类的方法对这个类的实例中的数据进行修改的话,程序是没有任何别的方法可以修改ValueObject类的实例中的数据,这个就是java的封装特性。对于不提供修改内部数据的方法的类,我们称为不可变(immutable)的类。在函数中对传入的参数变量进行赋值操作,只能在函数范围内改变局部变量指向的引用地址,但是不会改变原始地址的内容。因此,在changeValue2(...)函数内部的vo1和函数外的vo1虽然名字相同,但是实际上是不同的实例变量,只不过指向了和函数外的vo1同样的地址,所以当我们用vo1=... 对其进行赋值的时候,只不过是把函数内的临时变量指向了新的地址,并没有改变原始vo1内存地址中的内容。这就是在运行changeValue2(...)之后,vo1的值在main范围内仍然没有被修改的原因。而changeValue1里面是调用的ValueObject本身的function来更改其内容,因此是原始内存地址中的数据被更改了,所以是全局有效的。
发表于 2007-10-4 09:17:18 | 显示全部楼层
private static void changeValue2(ValueObject vo1) {

        vo1 = new ValueObject("B", 2);

        System.out.println("inside changeValue2: "+ vo1.getName());

                //=B,赋值操作引起的结果变化仅在changeValue2内部有效

    }

}
    对于这个函数被调用时,会创建一个局部变量的ValueObject类的引用v01,它的值与传进来的实参引用是一样的.也就是说指向你所传进来的对象,如果不把v01指向其它对象,而对其直接操作.是会影响到所传址(引用)进来的对象的.而例子中的private static void changeValue2(ValueObject vo1){....}函数不对传近来的对象做操作,而是直接把这个保存有实参引用的v01变量直接指向了一个新的ValueObject对象然后进物操作.改变的也只能是v01当前指向的对象的值(那个新的ValueObject对象).如果改成
private static void changeValue2(ValueObject vo1) {
           
        vo1.setName("Achange");//添加的操作
        vo1 = new ValueObject("B", 2);

        System.out.println("inside changeValue2: "+ vo1.getName());

                //=B,赋值操作引起的结果变化仅在changeValue2内部有效

    }

}

那么原始地址的值就会被改变了.

[ 本帖最后由 jenney 于 2007-10-4 09:24 编辑 ]
发表于 2009-4-5 11:00:25 | 显示全部楼层
您需要登录后才可以回帖 登录 | 建立账号

本版积分规则

 
QQ在线咨询

QQ|小黑屋|手机版|Archiver|美河学习在线 ( 浙网备33020302000026号 )

GMT+8, 2025-5-2 18:25

Powered by Discuz!

© 2001-2025 eimhe.com.

快速回复 返回顶部 返回列表