Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题。这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两个专业术语:

  • 按值调用(Call By Value)

  • 按引用调用(Call By Reference)

所谓的按值调用表示方法接收的是调用者提供的值,而按引用调用则表示方法接收的是调用者提供的变量地址(如果是C语言的话来说就是指针啦,当然java并没有指针的概念)。

Java程序设计语言确实是采用了按值调用,即Call By Value。也就是说方法得到的是参数值的一个拷贝,方法并不能修改传递给它的任何参数变量的内容。

下面我们来看一个基础数据类型的例子:

public class CallByValue {

  private static int x=10;

  public static void updateValue(int value){
value = 3 * value;
} public static void main(String[] args) {
System.out.println("调用前x的值:"+x);
updateValue(x);
System.out.println("调用后x的值:"+x);
} }
运行程序,结果如下:
调用前x的值:10
调用后x的值:10

可以看到x的值并没有变化,接下来我们一起来看一下具体的执行过程:

分析:

1)value被初始化为x值的一个拷贝(也就是10)

2)value被乘以3后等于30,但注意此时x的值仍为10!

3)这个方法结束后,参数变量value不再使用,被回收。

结论:当传递方法参数类型为基本数据类型(数字以及布尔值)时,一个方法是不可能修改一个基本数据类型的参数。

接下来我们看看引用数据类型又是怎么样的情况呢?我们还是一样先来看一个例子:

//声明一个User对象类型:

@Setter
@Getter
@AllArgsConstructor
public class User {
private String name;
private int age;
}
public class CallByValue {
private static User user=null;
public static void updateUser(User student){
student.setName("Lisi");
student.setAge(25);
} public static void main(String[] args) {
user = new User("zhangsan",26);
System.out.println("调用前user的值:"+user.toString());
updateUser(user);
System.out.println("调用后user的值:"+user.toString());
}
}

运行结果如下:

调用前user的值:User [name=zhangsan, age=26]
调用后user的值:User [name=Lisi, age=25]

很显然,User的值被改变了,也就是说方法参数类型如果是引用类型的话,引用类型对应的值将会被修改,下面我们来分析一下这个过程:

过程分析:

1)student变量被初始化为user值的拷贝,这里是一个对象的引用。

2)调用student变量的set方法作用在这个引用对象上,user和student同时引用的User对象内部值被修改。

3)方法结束后,student变量不再使用,被释放,而user还是没有变,依然指向User对象。

结论:当传递方法参数类型为引用数据类型时,一个方法将修改一个引用数据类型的参数所指向对象的值。

虽然到这里两个数据类型的传递都分析完了,也明白的基本数据类型的传递和引用数据类型的传递区别,前者将不会修改原数据的值,而后者将会修改引用所指向对象的值。可通过上面的实例我们可能就会觉得java同时拥有按值调用和按引用调用啊,可惜的是这样的理解是有误导性的,虽然上面引用传递表面上体现了按引用调用现象,但是java中确实只有按值调用而没有按引用调用。到这里估计不少人都蒙逼了,下面我们通过一个反例来说明(回忆一下开头我们所说明的按值调用与按引用调用的根本区别)。

public class CallByValue {
private static User user=null;
private static User stu=null; /**
* 交换两个对象
* @param x
* @param y
*/
public static void swap(User x,User y){
User temp =x;
x=y;
y=temp;
}
public static void main(String[] args) {
user = new User("user",26);
stu = new User("stu",18);
System.out.println("调用前user的值:"+user.toString());
System.out.println("调用前stu的值:"+stu.toString());
swap(user,stu);
System.out.println("调用后user的值:"+user.toString());
System.out.println("调用后stu的值:"+stu.toString());
}
}

我们通过一个swap函数来交换两个变量user和stu的值,在前面我们说过,如果是按引用调用那么一个方法可以修改传递引用所对应的变量值,也就是说如果java是按引用调用的话,那么swap方法将能够实现数据的交换,而实际运行结果是:

调用前user的值:User [name=user, age=26]
调用前stu的值:User [name=stu, age=18]
调用后user的值:User [name=user, age=26]
调用后stu的值:User [name=stu, age=18]

我们发现user和stu的值并没有发生变化,也就是方法并没有改变存储在变量user和stu中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝的值而已,最终,所做的事都是白费力气罢了。在方法结束后x,y将被丢弃,而原来的变量user和stu仍然引用这个方法调用之前所引用的对象。

这个过程也充分说明了java程序设计语言对对象采用的不是引用调用,实际上是对象引用进行的是值传递,当然在这里我们可以简单理解为这就是按值调用和引用调用的区别,而且必须明白即使java函数在传递引用数据类型时,也只是拷贝了引用的值罢了,之所以能修改引用数据是因为它们同时指向了一个对象,但这仍然是按值调用而不是引用调用。

总结:

    • 一个方法不能修改一个基本数据类型的参数(数值型和布尔型)。

    • 一个方法可以修改一个引用所指向的对象状态,但这仍然是按值调用而非引用调用。

    • 上面两种传递都进行了值拷贝的过程。

Java是值传递还是引用传递?的更多相关文章

  1. Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义

    一.Java中什么叫做引用类型变量?引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...

  2. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  3. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  4. java的值传递和引用传递

    昨天博主在对于值传递和引用传递这里栽了一个大坑啊,导致一下午时间都浪费在这里,我们先说下值传递和引用传递java官方解释: 值传递:(形式参数类型是基本数据类型):方法调用时,实际参数把它的值传递给对 ...

  5. java中方法的参数传递机制(值传递还是引用传递)

    看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参 ...

  6. java 对象传递 是 值传递 还是 引用传递?

    这个问题说实话我感觉没有太大的意义. 按第一印象和c++的一些思想去理解的话对象传递是引用传递,因为传递过去的对象的值能被改变. 但是又有很多人,不知道从哪里扣出来一句,java中只有值传递,没有引用 ...

  7. java参数传递时到底是值传递还是引用传递

    java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...

  8. Java面向对象-方法的值传递和引用传递

    Java面向对象-方法的值传递和引用传递 0 发布时间:『 2016-08-21 14:21』  博客类别:Java核心基础  阅读(197) 评论(0) Java面向对象-方法的值传递和引用传递 方 ...

  9. Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结

    这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...

  10. Java值传递和引用传递

    Java总是在讨论是传递还是引用传递,Java没有像C语言那样拥有指针,在看到引用传递和值传递很多的解释之后,更相信引用传递和值传递归根到底都是值传递,只不过引用传递的时候看上去很高大上,其实是把变量 ...

随机推荐

  1. luogu P5304 [GXOI/GZOI2019]旅行者

    传送门 所以这个\(5s\)是SMG 暴力是枚举每一个点跑最短路,然后有一个很拿衣服幼稚的想法,就是把所有给出的关键点当出发点,都丢到队列里,求最短路的时候如果当前点\(x\)某个相邻的点\(y\)是 ...

  2. 背景上实现阴影——linear-gradient

    /*从元素顶部有条阴影,两种方式,第二种更好,能控制阴影的宽度*/background-image: linear-gradient(0deg, rgba(226, 226, 226, 0) 97%, ...

  3. Loading class `com.mysql.jdbc.Driver'. The new driver class is `com.mysql.cj.jdb 问题

    是因为最新的数据库驱动的原因,用较早的版本就可以了. <dependency> <groupId>mysql</groupId> <artifactId> ...

  4. win10下安装Cygwin配置gcc编译环境

    首先要说明的是,我个人安装cygwin的用途是为了使用kenlm工具训练通及语言模型. 注:统计语言模型工具有比较多的选择,目前比较好的有srilm以及kenlm,其中kenlm比srilm晚出来,训 ...

  5. Nginx配置SSL证书部署HTTPS方法

    1.申请域名,绑定服务器ip(我申请的是阿里云服务器,以下就此为例) 2.可以在阿里云上免费申请SSL证书(下载证书,后续会用到) 3.在服务器中配置证书 在服务器上安装Nginx 将下载好的证书上传 ...

  6. MinGW GCC 8.3.1 2019年2月23日 出炉啦

    GNU 2019-02-22 发布了 GCC 8.3 https://gcc.gnu.org/onlinedocs/8.3.0/ 有详细的说明 MinGW 上可用的 GCC 8.3.1 版本下载地址 ...

  7. 【easy】746. Min Cost Climbing Stairs 动态规划

    On a staircase, the i-th step has some non-negative cost cost[i]assigned (0 indexed). Once you pay t ...

  8. JUC--闭锁 CountDownLatch

    CountDownLatch是一个同步辅助类,在完成一组正在其他线程中执行的操作之前,允许一个或者多个线程一直等待. 闭锁可以延迟线程的进度直到其到达终止状态,可以确保某些活动知道其他活动都完成才继续 ...

  9. WPF 10天修炼 第五天- 内容控件

    WPF内容控件 在WPF中,所有呈现在用户界面上的对象都称为用户界面元素.但是只有派生自System.Windows.Controls.Control类的对象才称为控件.内容控件通常是指具有Conte ...

  10. 将mysql中的一张表中的一个字段数据根据条件导入另一张表中

    添加字段:alter table matInformation add facid varchar(99)  default ''; 导入数据:update matInformation m set ...