在开始看我画小狗之前,咱们先来看道很简单的题目:

下面程序的输出是什么?

Dog myDog = new Dog("旺财");

changeName(myDog);

System.out.println(myDog.getName());public voidchangeName(dog) {

dog.setName("小强");

}

如果你的回答是“小强”,好,恭喜你答对了。下面我们改一下代码:

Dog myDog = new Dog("旺财");

changeName(myDog);

System.out.println(myDog.getName());public voidchangeName(dog) {

dog= newDog();

dog.setName("小强");

}

是的,我只是在changeName方法里面加了一句代码

dog = new Dog();

这一次的输出又是什么呢?

A旺财

B小强

答案是 A旺财,changeName方法并没有把myDog的名称改了。如果你答错了,没关系,我要开始画小狗了,画完你就明白了;如果你答对了,但不太明白其中的原因,那我画的小狗也肯定能帮到你。

myDog是什么

首先你要搞懂,代码里的变量myDog是什么?myDog真的就是一只狗吗?不!不是!myDog只是一条遛狗用的狗绳!

换句话说说,myDog并不是new出来的放在堆中的对象(object)!myDog只是一个指向这个对象实例的引用(reference)!如果你对Java的运行时数据区域足够了解,应该知道,这个引用是放在虚拟机栈上的。

参数传递

现在你知道了,myDog只是一条绳子,但这似乎并不能解释为什么changeName方法没有把myDog的名称改为“小强”,因为按照现有的理解,dog = new Dog(),就是把我的狗绳绑到另一只小狗身上,然后给这只小狗起名为“小强”,就像这样:

可事实是,myDog还是叫旺财,这是为什么?

问题就出在方法调用上,当我执行changeName(myDog)这一行代码时,myDog这条狗绳,被复制了一份,而传入到changeName方法里的那条狗绳(dog),就是复制出来的那一条,就像这样:

接着执行dog= new Dog(),这一行代码,就是把复制出来的那一条狗绳,从myDog解绑,重新绑到new出来的那只小狗上,也就是后来被起名为“小强”的小狗:

而myDog还是绑在旺财身上,这也就解释了,为什么执行完方法出来,myDog.getName()还是旺财。而在第一段代码里面,我们没有执行dog= new Dog(),也就没有改变dog所绑的小狗,dog还是绑在旺财身上,因此dog.setName(“小强”) 就把旺财的名字改成小强了。

string的例子

String str = "aaa";

changeString(str);

System.out.println(str);public voidchangeString(String str) {

str= "bbb";

}

如果你弄懂了上面那个例子,那么这里应该不难理解,changeString方法里,只是将新复制出来的引用str,指向另外一个字符串常量对象“bbb”,方法体外面的str并不受影响,还是指向字符串常量“aaa”,因此最终打印的还是aaa.

int的例子

int i = 1;

changeInt(i);

System.out.println(i);public void changeInt(inti) {

i= 2;

}

对于基本数据类型,他们没有引用,但是不要忘了,调用函数时,复制的动作还是会做的,执行changeInt(i)时,会将 i 复制到一个新的int上,传给changeInt方法,因此不管changeInt内部对入参做了什么,外面的 i 都不会受影响。最后打印出来的还是1.

值传递和引用传递

上面提到的参数传递过程中的复制操作,说白了,就是 = 操作。把上面那个int例子,做一下方法内联,其实就是这样:

int i = 1;//方法内联,相当于执行changeInt方法

int j = i; //新建一个和i一样的变量

j = 2; //修改j的值,i不变

System.out.println(i);

对于基本数据类型,= 操作将右边的变量(R_VALUE)完整的复制给左边的变量(L_VALUE),而对于对象,准确的说,应该是指向对象的引用(就像上面说的myDog),= 操作同样也是将右边的引用完整的复制给左边的引用,两者指向同一个对象实例。

这个 = 操作,是值传递和引用传递的根本差别,这也导致了值传递和引用传递有以下直观上的差别:

如果参数是值传递,那么调用者(方法体外部)和被调用者(方法体内部)用的是两个不同的变量,方法体里面对变量的改动不会影响方法体外面的变量。而之所以在Java可以在方法体内部改变方法体外部的对象,是因为方法体内部拿到了对象的引用,但是这个引用是和方法体外部的引用属于两个不同的引用的,方法体内部的引用指向别的对象,不会导致方法体外部的引用也指向别的对象。

如果参数是引用传递,那么调用者(方法体外部)和被调用者(方法体内部)用的是两个相同的变量,方法体里面对变量的改动会影响方法体外面的变量。

Java的变量都不是对象

通过上面的讲解,你也知道了一个很重要的点:Java里面的变量,要么是基本数据类型,要么是指向对象实例的引用类型(狗绳),绝对不会是一个对象(狗)。

刻画小狗状态java_用画小狗的方法来解释Java中的值传递相关推荐

  1. 用画小狗的方法来解释Java中的值传递

    在开始看我画小狗之前,咱们先来看道很简单的题目: 下面程序的输出是什么? 如果你的回答是"小强",好,恭喜你答对了.下面我们改一下代码: 是的,我只是在changeName方法里面 ...

  2. 用java如何画动物_用画小狗的方法来解释Java值传递

    笔者的个人博客 Bridge for You 已经上线,欢迎大家前去坐坐,喝茶侃大山! (这篇文章好像挺受欢迎的,借势给自己的个人网站做做宣传 ("'▽'")) 前言 在开始看我画 ...

  3. 用python画小仓鼠代码,用python画小仓鼠教程

    怎么用python绘图 你可以使用numpy和matplotlab这两个库来实现的你功能. 你的图可以参考:import matplotlibfrom numpy.random import rand ...

  4. 费尔马小定理素数java_费马小定理,我的理解

    原标题:费马小定理,我的理解 触碰标题下面一行的"邵勇老师"查看所有文章:触碰"数学教学研究", 关注本微信公众号(sx100sy). 本公众号内容均由邵勇本人 ...

  5. java方法调用原则,Java 中,在调用重载方法时,原则是(   )。_学小易找答案...

    [多选题]20世纪80年代后,国外企业伦理学进入了全面发展阶段,主要表现在( ). [判断题]扩展库numpy的isclose()和allclose()用来测试两个数组是否严格相等. [单选题]以下市 ...

  6. java如何实现成绩排序,小实例-实现对成绩总分由高到低的排序-Java中数组对象的排序...

    //如何实现这对象数组排序 import java.util.Arrays; public class SortTotalScore { public static void main(String ...

  7. java 删除已画出的线_如何删除java中的绘制线?

    问题是如何删除旧行?我的意思是,只在屏幕上显示当前的x和y行,使两行之间的交点"跟随"鼠标指针. 这是更新的代码: import javax.swing.*; import jav ...

  8. composition java_阿里P7架构师通过源码浅析Java中的资源加载

    一. 前提 最近在做一个基础组件项目刚好需要用到JDK中的资源加载,这里说到的资源包括类文件和其他静态资源,刚好需要重新补充一下类加载器和资源加载的相关知识,整理成一篇文章. 二. 什么是类加载器 虚 ...

  9. VS开发中的代码编写小技巧——避免重复代码编写的几种方法

    原文:VS开发中的代码编写小技巧--避免重复代码编写的几种方法 上一篇文章中程序员的幸福生活--有你的日子,每天都是情人节,收到了大家的很多好评.鼓励和祝福,非常感动,真诚的谢谢大家.也希望每个朋友都 ...

最新文章

  1. python一年365天、初始水平值_2020年11月7日,20201107
  2. sql server死锁的查询和解除
  3. 科普:算法岗是什么?我适不适合算法岗?选什么方向的算法岗?
  4. IIS的真正并发数及扩展并发的办法
  5. 前端学习(1514):vue-router使用步骤
  6. Sencha touch API
  7. Callable接口、Runable接口、Future接口
  8. vi定位到第一行,最后一行和任意行
  9. 通过import keyword查看python中定义的关键字
  10. Spring动态的切换数据源
  11. JAVA——二维数组打印
  12. php 降低采样率,讨论采样频率、采样深度(位深)、音量调节对音质的影响
  13. Windows垃圾清理BAT脚本
  14. 揭开姓氏的秘密|为什么最古老的八个姓氏都是女字旁?
  15. 转(逍遥子)Mosquito使用SSL/TLS进行安全通信时的使用方法
  16. 塔城地区谷歌高清卫星地图下载
  17. [Matlab]糖葫芦代码实现
  18. Dracula PRO 2021 零售版
  19. ajax的leiku,AJAX实现汉字和拼音搜索自动提示的效果(asp.net)
  20. 帕斯卡命名法(PascalCase)

热门文章

  1. mysql主从复制 主键 id_MySQL主从复制详解
  2. CSS构造六芒星图案
  3. 全网超详细的下载与安装VMware虚拟机以及为什么要安装VMware虚拟机
  4. JS向上取整、向下取整、四舍五入等集锦,一看就懂直接CV
  5. SharedMemory 使用介绍
  6. 【爬虫】403 Forbidden报错的解决办法
  7. Java springboot启动流程
  8. C++ P1137 旅行计划
  9. docker安装openwrt
  10. PHP取时间?php echo time() ?