Java:到底是值传递还是引用传递

先来看一段代码

public class MyClassA {


    public static void main(String[] args){

        String x = new String("hello");

        change(x);

        System.out.println(x);
    }

    private static void change(String x) {
        x = "world";
    }

}

输出结果是hello,那么change()方法中到底做了什么?

引用x指向在堆中的String对象”hello”,x作为参数传递到change()方法中,它仍然指向堆中”hello”。
这里写图片描述

下面重点来了
往往有一种错误的说话是这么讲的:
Java是值传递的,而x的值就是堆中对象”hello”的引用。当方法change()被调用时,由于String具有不可变性,所以在堆中会创建一个新对象”world”,而x是指向堆中对象”world”。
这里写图片描述

注意这种说法是错误的!!!

正确的解释应该是这样的:
当字符串”hello”被创建时,首先会在堆中开辟一块内存空间存储字符串对象所需要的内存空间。然后对象分配给在栈中的变量x,也就是说变量x引用堆中”hello”字符串对象。
变量x其实本身不是引用,栈中为了存储变量x开辟一块空间,其中变量x在其存储单元中存储了字符串对象”hello”在堆中的内存地址,这样就达到了变量x引用指向字符串对象的作用。
Java中只有值传递,当变量x作为参数传递给change(String x)方法时,参数x的值就是变量x也就是“hello”对象引用的一个副本,而不是“hello”对象复制一个引用副本给参数x。两种方式的区别在于变量x在传入change(String x)时,将存储单元存储的字符串对象的内存地址传递给了方法中参数x,参数x在栈中是开辟的另一块空间,这样参数x和变量x所存储的都是字符串对象的内存地址,这样两者就都指向了同一个字符串对象。
这样的解释是合理,但是String是具有不可变性的

x = "world";

由于String不可变,所以又创建了新的对象”world”。这时因为外部的变量x和方法内部的变量x两者是在栈中两块不同的空间,所以方法内部的x也就是参数x所引用的对象改变了,并不影响外部的变量x所指向的对象。
这里写图片描述
这里写图片描述

其实上面的说法有一点点不严谨,在change(String x)中,x = “world”;这个字符串对象应该是在常量池中的,因为字符串对象并不是通过new创建的,总之只要明白是新建了一个新的字符串对象就是了。

那么如果栈中的引用变量所指向的并不是一个String类型的对象,结果就不一样了。

... ...
class person {
public static String name = "Jack";
... ...
}
... ...
//定义一个改变对象属性的方法
public static void changeName(Person p) {
p.name = "Rose";
}
... ...
public static void main(String[] args) {
//定义一个Person对象,person是这个对象的引用
Person person = new Person();
//先显示这个对象的name属性
System.out.println(person.name);
//调用changeName(Person p)方法
changeName(person);
//再显示这个对象的name属性,看是否发生了变化
System.out.println(person.name);
}

第一次显示:“Jack”
第二次显示:“Rose”
和上面的道理一样,只不过这回堆中存放的对象是可变的。首先在主函数中引用变量person存放在栈中,person的存储单元中存放的是Person对象在堆中的内存地址。调用changeName(person)方法,将引用变量传递给方法参数p,参数p是栈中的另一块空间,person变量把其存储单元中存放的Person对象内存地址传递给了参数p,所以p也指向了同一个对象,然后在changeName方法中堆Person对象进行操作,所以经过changeName方法后Persond对象中的属性值改变了。
这里写图片描述

所以说Java中只存在值传递,无论是基本数据类型还是String类型或者其他的类都是值传递

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值