美文网首页
java的值传递和引用传递

java的值传递和引用传递

作者: 白泽1935 | 来源:发表于2017-11-10 10:01 被阅读0次

    大家好我是白泽。

    这篇打算讲讲java开发中新人要知道的一些事情吧

    对象引用和值引用,这个是在基础不过的知识了,但好多人特别是小白经常会忽略这问题,lz当初也是。如果你是大牛可以当看看或者直接跳过呗。

    提到这个概念我们先来大概了解下java中堆栈的东西,老话再谈,“栈”是存放java对象中的基本组成数据也就是所谓的基本数据类型和对象的引用,栈里的东西执行时都是单线程,你也可以理解为当有线程访问栈里的东西时栈都会克隆出一份新的让新线程操作,所以栈里的东西一般不存在线程安全问题。而“堆”存放就就是对象的信息栈中的引用会指向堆中这块对应的内存,在堆里一个对象只有一块内存,但可以被栈中多个引用地址引用,这就会出现一个应用改了这个对象其他引用取到的值也会相应的变化,这就会存在线程安全问题。当然线程这东西比较不好理解,这篇博客也不是和大家讲线程的所以大家只要知道栈中的数据一般不存在线程安全问题,而堆中的数据就会有线程安全问题暂时就够了。

    今天我们要讲的是我们平常开发必不可少的操作“传参”,传参就是往一个方法中传递参数,那这个又有什么好注意的呢?让lz一一道来,首先参数部分会有基本数据类型和对象引用构成那这个基础数据类型就是我们今天要讲的值传递,而对象引用就是对象的引用传递。大家也可以暴力一点记成在java中的参数里基础数据类型的参数就是值传递,对象就是一个引用传递。在这里新人要注意的是传进来的的参数如果是值引用可以随便的修改,因为上面说过它是存放在栈中是线程安全的,每次访问都会复制出一份出来所以相互之间不会影响。而引用传递就不是这样。首先需要注意的是,如果传进来的对象有这么个需求“你想用别人写的对象然后将它的引用作为方法参数传进来”那么这个对象在你的方法中切记千万不要直接的修改该类的数据和状态。因为可能只是你想要这个对象的数据变化而写这个对象的同事或者其他使用这个对象的同事并不希望这对象的值有变化,这时你要是直接修改的话那就会出现后期可能连你自己都不知道的bug而且这种bug不容易找出来。为什么会出现这种情况呢?上面提到过,对象是放在堆中的如果你使用的时候不是重新new出来一个那么你使用的引用也是指向和别人使用的同一块内存,这样你改了别人当然也会有变化。这其实也算是一种线程安全的表现吧。

    那么如何避免这种bug呢?首先如果你只是想用这个对象而不是对象里的别人的数据,那你只要自己new出来然后自己赋值初始化再传进去就可以。因为使用new关键字创建的对象会在堆内存中分配一个新的内存给你这个对象,同样在栈中也会生成一个新的引用给你。那要是想用别人的数据呢?这就要使用克隆的方法去把该对象克隆出来再使用或者自己提供一个该对象的克隆方法即:new出一个新对象之后再把另一个对象的数据set进去再使用就好。另外比较快捷的方式就是实现java提供的Cloneable接口重写它的clone方法再使用,但这个方法只是浅复制,也就是说它只会复制对象里存在栈里边的数据也就是基本数据类型的数据,而如果这个对象有其他对象的引用那么如果你修改那个被引用的对象还是会被修改掉,除非你再使用这个方法再给那个对象进行克隆。但是这种方式是不是听着就感觉很low?,别急,试试下一种。就是实现java提供的Serializable序列化接口再使用io对其进行序列化,再反序列化回来的对象就是一个全新的对象,也就是说在堆中有自己的内存地址,对其修改不会影响别人的对象的数据。

    下面看一个内存图,其中有两个对象引用同时指向同一个对象,而此时一个修改数据,一个获取数据但是操作的都是同一个对象的数据这样就会参生数据错乱的额情况

    好了,第一遍入行博客就写到这了,以后讲讲在工作中的经验和积累,大家有兴趣可以关注微信公众号 baize1935 获取更过文章。

    相关文章

      网友评论

          本文标题:java的值传递和引用传递

          本文链接:https://www.haomeiwen.com/subject/jdovmxtx.html