java中参数传递

总之一句话:java中只有副本传递,对于值,拷贝值,对于引用,拷贝引用(对于数组,数组名传递的都是引用)。

/**
 * java中只有副本传递,对于值,拷贝值,对于引用,拷贝引用(对于数组,数组名传递的都是引用)。
 * @author sargeles
 */
public class About_Onlycopytransmit {
    /**
     * 测试一组:基本类型传递是按值传递,意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。
     * String因为两个原因表现出基本类型的特征: 一个是String实际上操作的是char[],可以理解为String是char[]的包装类
     * 二是给String变量重新赋值后,实际上没有改变这个变量的值,而是重新new了一个String对象,这里涉及到String不可变这一特性。
     */
    static void ceshi1() {
        int i = 1;
        String s = new String("I'll change you!");
        A a = new A();
        a.change(i, s);
        a.show();
        System.out.println("被传入并修改的i=" + i);
        System.out.println("被传入并修改的s=" + s);
    }
    /**
     * 测试二组:引用类型传递是副本传递,意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。
     * 但需要注意到的是,ceshi2里定义的b,会被直接传递给a,作为a的属性,而不是复制给a,
     * 也就是说对象b并不会被拷贝,对change()传递参数后,A.b与b指向同一个对象。 也是遵循‘引用传递’这四个字。
     */
    static void ceshi2() {
        int[] intarray = { 0, 1, 2 };
        String[] strarray = { "aaa", "bbb", "ccc" };
        A a = new A();
        B b = new B(1);
        a.change(intarray, strarray, b);
        a.show();
        System.out.println("被传入的i=" + intarray[1]);
        System.out.println("被传入的s=" + strarray[1]);
        System.out.println("被传入的b.index=" + b.index);
        System.out.println("被传入的b的hash值=" + b.hashCode());
    }
    /**
     * 为了进一步证实ceshi2中的引用传递,这次我们测试的是数组的引用,而不是对象的引用。
     */
    static void ceshi3() {
        int[] intarray = { 0, 1, 2 };
        A a = new A();
        a.change(intarray);
        a.show();
        System.out.println("被传入的intarray=" + intarray);
        System.out.println("被传入的intarray[0]=" + intarray[0]);
    }
    public static void main(String[] args) {
        ceshi1();
        //ceshi2();
        // ceshi3();
    }
}
class A {
    int i = 0;
    int[] ii = { 0, 1, 2 };
    String s = "I'm not changed!";
    B b = new B(0);
    /**
     * ceshi1专用
     */
    void change(int i, String s) {
        this.i = i;
        i++;
        this.s = s;
        s = "I'll change you!But I have been changed too!";
    }
    /**
     * ceshi2专用
     */
    void change(int[] i, String[] s, B b) {
        this.i = i[1];
        i[1]++;
        this.s = s[1];
        s[1] = "I'll change you!But I have been changed too!";
        this.b = b;
        // 下面的语句改为 this.b.index++; 效果不变。
        b.index++;
    }
    /**
     * ceshi3专用
     */
    public void change(int[] intarray) {
        this.ii = intarray;
        intarray[0]++;
    }
    public void show() {
        if (i != 0)
            System.out.println("A的对象a中i=" + i);
        if (ii[0] != 0) {
            System.out.println("A的对象a中ii=" + ii);
            System.out.println("A的对象a中ii[0]=" + ii[0]);
        }
        if (!s.equals("I'm not changed!"))
            System.out.println("A的对象a中s=" + s);
        System.out.println();
        try {
            if (b.index != 0) {
                System.out.println("A的对象a中b.index=" + b.index);
                System.out.println("A的对象a中b的hash值=" + b.hashCode());
                System.out.println();
            }
        } catch (java.lang.NullPointerException e) {
            System.out.println("未得到B对象!");
        }
    }
}
class B {
    int index = 0;
    public B(int i) {
        index = i;
    }
}

ceshi1的输出:

A的对象a中i=1
A的对象a中s=I'll change you!
被传入并修改的i=1
被传入并修改的s=I'll change you!

ceshi2的输出:

A的对象a中i=1
A的对象a中s=bbb
A的对象a中b.index=2
A的对象a中b的hash值=2046587545
被传入的i=2
被传入的s=I'll change you!But I have been changed too!
被传入的b.index=2
被传入的b的hash值=2046587545

ceshi3的输出:

A的对象a中ii=[I@62af9d74
A的对象a中ii[0]=1
被传入的intarray=[I@62af9d74
被传入的intarray[0]=1

关于引用传递,如果还看不懂,不妨继续看下去。
在ceshi2中,执行第92行语句的之前,两个b是不同的id,一个是25,一个是21,说明是不同的实例。
这里写图片描述

执行后,可以看到两者变为同一id,说明引用被拷贝并传递了,现在已经没有引用指向B的id为25的实例。
这里写图片描述

在执行94行语句的时候,同时改变了两个地方,说明this.b和b只是同一个实例对象的不同引用而已。它们内部的属性值是一样的。
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值