理解Java按值传递&按引用传递

本文深入探讨Java中参数传递机制,区分基本数据类型与引用类型的不同,并通过具体代码示例,详细解释按值传递和按引用传递的区别,尤其是对String、Integer及StringBuffer等类型的行为进行了解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自己的理解,如有理解的不对的地方,欢迎指出!

大家都知道的,在Java中,是这样子的:

  • 基本数据类型------- 按值传递
  • 包装类型------------ 按引用传递

举例:

public static void main(String[] args) {
        int a = 1;
        StringBuffer s1 = new StringBuffer("hello");
        System.out.println("原始的a:"+a+"    原始的s1:"+s1);
        change(a,s1);
        System.out.println("后来的a:"+a+"    后来的s1:"+s1);
    }

    private static void change(int a, StringBuffer s1) {
        a = 2;
        s1.append(" world!");
    }
 结果:
 原始的a:1    原始的s1:hello
 后来的a:1    后来的s1:hello world!

完美验证上述观点!
那。。,再看一例

public static void main(String[] args) {
        Integer a = 1;
        Integer b = a;
        System.out.println("原始的a:"+a+",hashcode:"+a.hashCode()+"    原始的b:"+b+",hashcode:"+b.hashCode());
        b++;
        System.out.println("后来的a:"+a+",hashcode:"+a.hashCode()+"    后来的b:"+b+",hashcode:"+b.hashCode());

        String str1 = "lalalala";
        System.out.println("原始的str1:"+str1+"    ,   hashcode:"+str1.hashCode());
        changeStr(str1);
        System.out.println("后来的str1:"+str1+"    ,   hashcode:"+str1.hashCode());
    }

    private static void changeStr(String str1) {
        System.out.println("before changeStr: "+str1+"    ,   hashcode:"+str1.hashCode());
        str1 = "xixixixi";
        System.out.println("after changeStr: "+str1+"    ,   hashcode:"+str1.hashCode());
    }
结果:
原始的a:1,hashcode:1    原始的b:1,hashcode:1
后来的a:1,hashcode:1    后来的b:2,hashcode:2

原始的str1:lalalala    ,   hashcode:-1676657068
before changeStr: lalalala    ,   hashcode:-1676657068
after changeStr: xixixixi    ,   hashcode:918596164
后来的str1:lalalala    ,   hashcode:-1676657068

问题来了: 按引用传递,为什么没有变?
原因:

  • 基本类型的包装类型都是不可变量,所以上面的b,在经过b++后,输出来的b的值是2,但是现在的b已经不是原来的b了,可以看得到,hashcode是不一样的【Integer 内部对hashcode进行了重写,hashcode就是它的值】
  • String类型是引用类型,同样他也是不可变量,传参的时候传的是引用没有错,但是要明白,引用也是按值传递的。也就是说传过来的str1是引用,它也是一个值,这个值是不可变的。下面的 str1 = “xixixixi”;,改变的不是str1,而是重新开辟了一个地址,然后赋值给str1,所以在这个函数里面,似乎str1变了,但是这个str1已经不是原来的str1了。由于string是不可变量,所以原始的str1并没有发生改变

再看一个例子:

public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer("hello");
        StringBuffer s2 = new StringBuffer("hello");
        System.out.println("原始的s1:"+s1+",hashcode:"+s1.hashCode()+"    原始的s2:"+s2+",hashcode:"+s2.hashCode());
        change(s1,s2);
        System.out.println("后来的s1:"+s1+",hashcode:"+s1.hashCode()+"    后来的s2:"+s2+",hashcode:"+s2.hashCode());
    }

    private static void change(StringBuffer ss1, StringBuffer ss2) {
        ss1.append(" world!");
        ss2 = ss1;
        System.out.println("change:  ss1: "+ss1+",hashcode:"+ss1.hashCode()+"   ss2: "+ss2+",hashcode:"+ss2.hashCode());
    }
结果:
原始的s1:hello,hashcode:1163157884    
原始的s2:hello,hashcode:1956725890
change:  ss1: hello world!,hashcode:1163157884   
		 ss2: hello world!,hashcode:1163157884
后来的s1:hello world!,hashcode:1163157884    
后来的s2:hello,hashcode:1956725890

这又是为什么?StringBuffer并不是不可变类啊?为什么s2的值并没有改变?
还是那句话:引用也是按值传递的
解释:传递s1,s2的引用就可以理解为传递了两个地址0X11111111,0X22222222,而且这两个地址是按值传递的(也就是传递了两个值0X11111111,0X22222222)。
在调用ss1.append(" world!");时,会修改ss1所指向的字符串的值,因此会修改s1的值。但是在执行ss2 = ss1;时,只会修改ss2的值而对s2毫无影响。
简单的说:如果时引用类型的化,你是不是改变了我指向的地方(也就是老家),如果直接改变了老家的值,就是变了,如果你改变了是我的值,就和我的老家没有关系,就不会改变老家的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值