Java中的值传递和引用传递

在Java中存在值传递和引用传递,但是如何去区分两者呢,现在来说一下我自己的理解,希望能帮到需要的人理解这部分内容。

先来看一段概念:

值传递:传递的是值的拷贝,对传递的值做处理不会修改值本身(相应的理解可以思考虚拟机,我们传递的值是从虚拟机中拷贝的一份,原始的值是不会变。)

引用传递:将原数据作为参数进行传递,修改传递的值会修改原数据本身。 一句话总结:值传递不修改原数据,引用传递是直接操作原数据。

好了,看概念都知道说的什么,但是理解又是一回事,现在用代码来理解值传递和引用传递。

先上第一个例子:

public class Test {
    public static void test(Integer i){
        i = 7;
    }
    public static void main(String[] args){
        int x = 0 ;
        test(x);
        System.out.println("x="+x);  //输出i=0
    }
}

即使我不写输出结果你们也能知道这个一定是输出i=0,我们看调用方法,传递给调用方法的参数是x=0,于是就相当于我们只是给调用方法的参数传递了一个数字0,因此在test方法中对传入的0做处理是不会影响原数据本身。

第二个例子:

public class Test {
    public static void test(String str){
        str = "world";
    }
    public static void main(String[] args){
        String string = "hello";
        test(string);
        System.out.println(string);	//输出hello
    }
}

当我们参数类型改为字符串时,对于传入的字符串,在调用方法中并不存在修改自身的方式,其中 str=“world” 并没有修改存储在常量池中的的原数据,因此依然输出 hello。

第三个例子:

public class Test {
    public static void test(StringBuffer str){
        str.append("world");
    }
    public static void main(String[] args){
        StringBuffer stringBuffer = new StringBuffer("hello ");
        test(stringBuffer);
        System.out.println(stringBuffer);   //输出hello world
    }
}

这个例子中在调用方法中多了一个append方法,该方法会对传入的参数做修改,同时改变常量池中的数据,append本身是对自身进行的操作,因此常量池中的hello会改变为hello world。

第四个例子:

public class Test {
    public static void test(StringBuffer str){
        str = new StringBuffer("hi");
        str.append("world");
    }
    public static void main(String[] args){
        StringBuffer stringBuffer = new StringBuffer("hello ");
        test(stringBuffer);
        System.out.println(stringBuffer);   //输出hello
    }
}

在这个例子中我们看到调用方法中对传入的参数进行了new对象,同时我们也知道new是新生成一个对象,并不会影响原来的对象,因此我们可以看到在test方法中我们new了一个新对象,新对象指向了hi这个字符串,同时对hi执行了append,这些操作都是对new对象做的操作,传入的hello对象并没有受到影响。因此还是输出hello。(该部分的理解可以结合虚拟机的存储结构进行理解。结构图就不画了。)

第五个例子:

public class Test {
    public static void test(StringBuffer str){
        StringBuffer str2 = new StringBuffer("Hi ");
        str = str2;
        str2.append("world");
        System.out.println("str="+str); //输出Hi world
        System.out.println("str2="+str2); //输出Hi world
    }
    public static void main(String[] args){
        StringBuffer stringBuffer = new StringBuffer("hello ");
        test(stringBuffer);
        System.out.println(stringBuffer);   //输出hello
    }
}

在该例子中可能会疑惑在调用方法中使用了str = str2,并且在输出str是也是输出str = Hi world,为什么最后输出的依然是hello,这依然要回到虚拟机存储结构问题,在str = str2;之前str指向的一直都是“hello ”,执行了该操作,str的指向就变为了“Hi ”,因此test方法中str = str2,其实是将str2的地址赋值给了str,因此这时str指向的其实是“Hi ”,因此对str2做任何操作,str也会做出相应的改变。但是stringBuffer 依然是存在常量池中不会改变。

总结:当传入的参数类型为基本类型时,都是值传递,并不会改变值本身,当传入的参数类型为对象时,其实传入的是对象的地址,这就需要考虑是否在调用方法中存在修改自身的方法。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值