[Java]值传递

本文详细解析Java中的参数传递机制,对于基本数据类型,总是进行值传递,方法内的改变不会影响外部变量。而对于引用数据类型,虽然传递的是对象的引用,但只有当在方法内直接操作对象属性时,外部变量才会同步改变。当在方法内重新创建对象时,内外部变量不再关联。另外,String等常量池内的数据类型,其行为类似引用类型,但内部改变同样不会影响外部。
摘要由CSDN通过智能技术生成

在Java中都是值传递的


基本数据类型

在调用方法时,都是将变量的值传递给形参,而后对形参进行操作,而不是对该变量的值进行操作
例如:

class Hello{
    
    public static void main(String[] args){
        
        int num = 1;
        add(num);  //这里输出num值为2
        System.out.println(num);  //这里输出num值为1
        //在方法add中虽然参数名与主函数中定义的变量名一样,但是是在不同栈帧中的不同变量,一个变量的值的改变并不会影响另一个变量的值。
    }
    
    public static void add(int num){
        
        num++;
        System.out.println(num);
    }
}

学过指针就容易理解,在 Java中就相当于没有使用指针,因而方法中的参数与传入的参数是两个地址,一个值的改变不会影响另一个值


引用数据类型

在之前**[Java]面向对象概念**博文中提到过,引用数据类型实际上存储的值为该对象在堆中的地址,所以与基础数据类型不同,调用方法是若是参数为引用数据类型,在方法体内操作数据,实质上操作的是堆中该对象的属性,因此会同步引起该数据类型的改变

例如:

class Hello{
    
    public static void main(String[] args){
        
        Student student = new Student("张三", 1);
        
        changeName(student);
        
        System.out.println(student.name);  //此时打印的值为 李四
    }
    
    public static void changeName(Student student){
    
        student.name = "李四";
    }
}

class Student{
        
        String name;
        int num;
        
        public Student(String name, int num){
            
            this.name = name;
            this.num = num;
        }
 }

但是并不是说java这里就是引用传递,在本文中第一句都提过 java永远都是值传递。但是这里传递的值是堆中对象的地址,才能够引起外部变量的同步改变。

因此,引用数据类型并不是在所有场合下都会跟上面示例一样,会发生方法内变量改变影响方法外变量的情况

例如:

class Hello{
    
    public static void main(String[] args){
        
        Student student = new Student("张三", 1);
        
        changeName(student);
        
        System.out.println(student.name);  //此时打印的值仍为 张三
    }
    
    public static void changeName(Student student){
    
        student = new Student("李四", 2);
    }
}

class Student{
        
        String name;
        int num;
        
        public Student(String name, int num){
            
            this.name = name;
            this.num = num;
        }
}

上面代码唯一一处改变就是changeName函数中虽然接收了外部参数student(外),但在方法体内又为student(内)重新new了一个对象,此时在堆中也新开辟了一块空间来管理该对象的属性信息,地址当然也与之前不同,student(内)存储的地址也指向了该地址,而student(外)存储的地址仍然指向原先的对象,因此,两个student此时已经没有了联系,指向了两个不同的对象,故修改student(内)的属性信息并不会影响到student(外)的属性信息


String等常量池有关数据类型

这种情况其实与引用数据类型中的第二种情况相似,都是内部变量的改变并不影响外部变量的改变

例如:

class Hello{
    public static void main(String[] args){
        
        String str = "张三";
        changeString(str);
        
        System.out.println(str);  //此时打印的值仍为 张三
    }
    
    public static void changeString(String str){
        
        str = "李四";
    }
}

首先在main函数中定义str(外)时,就在常量池内开辟了一个空间用于存储“张三”,此时str(外)的值为该空间的地址。在调用changeString函数时,执行 str = “李四” 语句之前,str(内)与str(外)的值是相同的,都是指向常量池内值为“张三”的空间的地址。而在执行该语句时,程序在常量池内又开辟了一块空间用来存储“李四”,此时str(内)的值变更为常量池内“李四”的地址,而str(外)的值仍然为“张三”的地址,此时两个str也已经没有了联系,故打印出来的值还是“张三”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值