Java:传值和伪传引用

基本概念

传值:传递的是值的副本。方法中对副本的修改,不会影响到调用方。传引用:传递的是引用的副本,共用一个内存,会影响到调用方。此时,形参和实参指向同一个内存地址。对存储了引用副本(对象的地址)的引用变量的修改,如设置为null,重新指向其他对象,不会影响到调用方。其实,在Java中所有的参数都是传值的,引用符号&的传递是C++中才有的。对于普通对象(非fianl修饰的类类型对象)而言,不是将对象本身传递给方法,而是将对象的引用或者说对象的首地址传递给方法,对于引用变量来说,它是按值传递的,传递的是本身存储的对象的地址的副本,但由于这种传值的确让形参和实参指向同一个内存地址,使得形参对自身引用对象的修改会实际影响到实参,所以可把普通对象传递给形参的方式称为伪引用方式。

代码示例

传值

传递基本数据类型的值(byte/byte[],short/short[],int/int[],long/long[],double/double[],float/float[],char/char[],boolean/boolean[])。

// 基本数据类型
public class ParamChangeValue {    
    public static void main(String[] args) {        
        int s=11;
        System.out.println("s="+s);
        change(s);
        System.out.println("s="+s);
    }    
    private static void change(int i){ 
        i = 22;    
    }
}

运行结果

s=11
s=11

从运行结果可知,把int类型的变量s(实参)传递进方法,并且在方法中这个参数(形参)也进行了修改后,实参s并没有被修改,即传值传递传的是值的副本,而不会影响到本身。

传引用

传递普通类类型的对象。

// 对象
class A {

    public int a = 0;
    public int b = 0;

    public A(int a, int b) {
        this.a = a;
        this.b = b;
    }
    
    public void print(){
        System.out.println("a="+a+",b="+b);
    }
}
public class ObjectChangeValue {
    
    private static void changeObject(A bb){ 
        bb.a=33;
        bb.b=44;
    }

    public static void main(String[] args) {
        A aa = new A(11, 22);
        aa.print();
        changeObject(aa);
        aa.print();  
    }
}

运行结果

a=11,b=22
a=33,b=44

从运行结果可知,对象aa的a和b属性被修改了,这说明方法调用语句changeObject(aa);并不是把aa所引用的对象的副本赋给bb,而是把aa所引用的对象的地址赋给了bb,如此,对bb的修改即为对aa的修改。地址即为引用,因为引用类型变量aa存储的是aa所引用对象的地址,而方法调用时传递的就是aa所引用对象的地址,即是把aa的副本传递了进去,从这一点看,这所谓的“传引用”也是“传值”,传给形参的是实参的副本。而由于这个副本不是对象本身,而是对象的地址,即引用,因此,也把引用类型的实参和形参之间的传递也被称为“传引用”。另外要注意一点的是,如果对象被重新创建或赋值为null,即new会重新指向其他对象,不影响其原对象的值。

传引用(final)

传递由final修饰的类类型的对象,如传递String、Integer等immutable(不变的)类型的对象。

// String、Integer、Long等
public class StringChangeValue {   
    public static void main(String[] args) {       
        String aa="string_aa";
        System.out.println(aa);
        changeString(aa);
        System.out.println(aa);  
    }
     
    private static void changeString(String bb){
        bb="string_bb";
    }
}

输出:

string_aa
string_aa

从运行结果可知,String类型的变量aa并没有改变,原因是String、Integer、Double等immutable(不变的)类型是被final修饰的,是final的,由这些类型所定义的变量所引用的对象是不可修改的,只能给变量重新赋值或生成对象。

总结

基本类型(byte,short,int,long,double,float,char,boolean)为传值;对象类型(Object,数组,容器)为传引用;String、Integer、Double等immutable类型因为类的变量设为final属性,无法被修改,只能重新赋值或生成对象。当Integer作为方法参数传递时,对其赋值会导致原有的引用被指向了方法内的栈地址,失去原有的的地址指向,所以对赋值后的Integer做任何操作都不会影响原有值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值