integer是值传递还是引用传递_值传递与引用传递

55e4d6951be5e19377c967124ba5cc74.png
值传递:指的是在方法调用时,传递的是参数是按值的拷贝传递。
特点:传递的是值的拷贝,也就是传递后就互不相关了。
引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。
特点:传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

对于这两种传参方式,假如你写过一些java程序后,你就会发现这不就是看传的参数是基本类型的还是引用类型的吗?(其中比较特殊一点的是String类型和基本类型的包装类类型,它们也是按值传递的,但它是属于引用类型,对于还不知道包装类型的,可以看我之前的一篇博客:现世安稳:java学习基础(三)关于自动拆箱与自动装箱)

一、值传递

话不多说,我们直接分析代码运行结果:

public 

63b19f60eceab9a05e288c9dc8cba943.png
测试基本类型值传递

对于基本类型,这里我只举了int类型的值传递例子,可以看到在main方法里的a与test1方法里面的a并没有什么关系,在test1方法里面改变a的值并不能影响main方法里的a值。

264e35514b8c6b0fe7f7db61c6061d50.png
值传递,二者并不影响

那对于引用类型String和基本类型的包装类而言,它们也都是值传递。所以我们先来了解一波String类型。

public 

85c4b4350ba32917168c98570edbbc58.png
String类型采用值传递

分析上面代码,可以看出与int类型值传递的效果是一样的。

对于String类型,我们有两种常用的创建对象的方法,一种是用字符串直接量,一种是用字符数组。但java把字符串直接量也当做是String对象,因此,利用字符串直接量可以按如下两种方式去创建。

//利用字符串直接值创建对象的方法

但这两种方式却不能说完全一样,且看测试代码如下:

4876c12b3327e62af8caed9475851603.png

bbfefaf9c4865a350a7a878a0b69a2ee.png

根据==判断为false可知二者并不是指向同一个引用,但我们之前说String类型对象是不可变得,它的内容是不能改变的,既然根据equals判断为true,它们的内容是一样的,那为什么二者却不是指向同一个引用呢?

其实,很简单,正是由于字符串在程序设计中被频繁使用,当它本身又不可变,所以JVM为了提高效率并节约内存,对具有相同字节序列的字符串直接量使用同一个实例。这个实例叫做“限定(interned)的字符串”。因此两种创建对象的方式其实是不同的,s2是指向了一个限定的字符串“hello”,这个是在栈内存中的,而s1则是实实在在指向了创建的一个字符串对象,它的值为“hello”,这个则是在堆内存的。

6b8d6b35f26d284dd88d8f612d0d9300.png
两种创建方式的比较

假如你对什么是限定字符串和字符串不可变性的概念理解了,下面的一段代码你就应该能很快理解了:

public 

9150077a9e62c58e8913ccfb228f0f2f.png

分析:首先对于s1和s4大家应该好理解,创建了两个对象,引用肯定是不相同的;其次对于限定字符串“hello”,由于s2与s3均指向它,因此二者的引用是相同的,所以s2==s3为true。至于s1和s2,上面已经解释过了。最后我再说明一下String类型的不变性。看到s3输出为helloworld,不明所以的你可能以为这个不就和不变性矛盾了吗?其实不然,且看下图:

19b040fc6901482730f1ccb79b85f842.png
不变性图解(注:此图有问题,"hello"以及“helloworld”都应该在栈内存中)

看完图,你就会明白,不变的是“hello”,但s3的引用关系发生了改变,指向了存放"helloworld"的内存空间。

二、引用传递

看完上面int和String类型的值传递,我们再来看下什么是引用传递。事实上,java里面参数传递只有值传递一种,因为引用传递可以相当于传递的是引用值。至于引用值是什么,我们可以类比C语言得指针变量,它存放的也是一段内存空间的地址。

引用传递事实上更好理解,尤其是你对C语言中指针概念有所了解的话,这个直接分析一遍代码,就能理解了。

public 

f4267d284af3ed9869cc69396a4f9cee.png
引用传递测试结果

首先在main方法中,我们创建了A类的一个对象a,并把它的age设为2,然后我们将a作为参数传到test1方法中,并再次修改age值,然后输出test1中a.age值,执行完后返回到main函数里,再输出main中a.age,且二者结果一致。结合内存图示来理解,会很容易理解:

9435c2f7b12ee78dac7b1159df963a23.png
引用传递

在不同方法之间,看似传递的是一个对象,但其实对象的位置并没有动,只是将存放对象的内存地址进行了传递,这样当改变对象的一些属性时,也会的的确确改变堆内存中对象的某些属性值,因此返回到main函数后由于a依旧指向同一块区域,所以去读取数据的时候,值就会变化了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值