怎么在Java中实现值传递和引用传递

发布时间:2021-04-20 15:33:58 作者:Leah
来源:亿速云 阅读:1044

怎么在Java中实现值传递和引用传递?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

Java的特点有哪些

Java的特点有哪些 1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 2.Java具有简单性、面向对象、分布式、安全性、平台独立与可移植性、动态性等特点。 3.使用Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。

1、什么是值传递,什么是引用传递?

2、值传递和引用传递的区别是什么?

怎么在Java中实现值传递和引用传递 

3、Java中只有值传递

3.1 纠正一下大家以前的那些错误看法

错误理解一:值传递和引用传递,区分的条件是传递的内容,如果是个值,就是值传递。如果是个引用,就是引用传递

错误理解二:Java是引用传递。

错误理解三:传递的参数如果是普通类型,那就是值传递,如果是对象,那就是引用传递。

3.2求值策略

我们说当进行方法调用的时候,需要把实际参数传递给形式参数,那么传递的过程中到底传递的是什么东西呢?

这其实是程序设计中求值策略(Evaluation strategies)的概念。

在计算机科学中,求值策略是确定编程语言中表达式的求值的一组(通常确定性的)规则。求值策略定义何时和以何种顺序求值给函数的实际参数、什么时候把它们代换入函数、和代换以何种形式发生。

求值策略分为两大基本类,基于如何处理给函数的实际参数,分为严格的和非严格的。

3.3 严格求值

在“严格求值”中,函数调用过程中,给函数的实际参数总是在应用这个函数之前求值。多数现存编程语言对函数都使用严格求值。所以,我们本文只关注严格求值。

在严格求值中有几个关键的求值策略是我们比较关心的,那就是传值调用(Call by value)、传引用调用(Call by reference)以及传共享对象调用(Call by sharing)

1.传值调用(值传递):在传值调用中,实际参数先被求值,然后其值通过复制,在传递给被调函数的形式参数。因为形式参数拿到的只是一个"局部拷贝",所以如果在被调函数中改变了形式参数的值,并不会改变实际参数的值。

2.传引用调用(引用传递)在传引用调用中,传递给函数的是它的实际参数的隐式引用而不是实参的拷贝。因为传递的是引用,所以,如果在被调函数中改变了形式参数的值,改变对于调用者来说是可见的。

3.传共享对象调用(共享对象传递)传共享对象调用中,先获取到实际参数的地址,然后将其复制,并把该地址的拷贝传递给被调函数的形式参数。因为参数的地址都指向同一个对象,所以我们也称之为"传共享对象",所以,如果在被调函数中改变了形式参数的值,调用者是可以看到这种变化的。

不知道大家有没有发现,其实传共享对象调用和传值调用的过程几乎是一样的,都是进行"求值"、"拷贝"、"传递"。你品,你细品。

但是,传共享对象调用和内传引用调用的结果又是一样的,都是在被调函数中如果改变参数的内容,那么这种改变也会对调用者有影响。你再品,你再细品。

那么,共享对象传递和值传递以及引用传递之间到底有很么关系呢?

对于这个问题,我们应该关注过程,而不是结果,因为传共享对象调用的过程和传值调用的过程是一样的,而且都有一步关键的操作,那就是"复制",所以,通常我们认为传共享对象调用是传值调用的特例

我们先把传共享对象调用放在一边,我们再来回顾下传值调用和传引用调用的主要区别:

传值调用是指在调用函数时将实际参数复制一份传递到函数中,传引用调用是指在调用函数时将实际参数的引用直接传递到函数中。

怎么在Java中实现值传递和引用传递

3.3 java 的求值策略

前面我们介绍过了传值调用、传引用调用以及传值调用的特例传共享对象调用,那么,Java中是采用的哪种求值策略呢?

很多人说Java中的基本数据类型是值传递的,这个基本没有什么可以讨论的,普遍都是这样认为的。

但是,有很多人却误认为Java中的对象传递是引用传递。之所以会有这个误区,主要是因为Java中的变量和对象之间是有引用关系的。Java语言中是通过对象的引用来操纵对象的。所以,很多人会认为对象的传递是引用的传递。

而且很多人还可以举出以下的代码示例:

public static void main(String[] args) {
  Test pt = new Test();
 
  User hollis = new User();
  hollis.setName("Hollis");
  hollis.setGender("Male");
  pt.pass(hollis);
  System.out.println("print in main , user is " + hollis);
}
 
public void pass(User user) {
  user.setName("hollischuang");
  System.out.println("print in pass , user is " + user);
}

 输出结果:

print in pass , user is User{name='hollis', gender='Male'}
print in main , user is User{name='hollischuang', gender='Male'}:

可以看到,对象类型在被传递到pass方法后,在方法内改变了其内容,最终调用方main方法中的对象也变了。

所以,很多人说,这和引用传递的现象是一样的,就是在方法内改变参数的值,会影响到调用方。

但是,其实这是走进了一个误区。

其实Java中使用的求值策略就是传共享对象调用,也就是说,Java会将对象的地址的拷贝传递给被调函数的形式参数。只不过"传共享对象调用"这个词并不常用,所以Java社区的人通常说"Java是传值调用",这么说也没错,因为传共享对象调用其实是传值调用的一个特例。

值传递和共享对象传递的现象冲突吗?

看到这里很多人可能会有一个疑问,既然共享对象传递是值传递的一个特例,那么为什么他们的现象是完全不同的呢?

难道值传递过程中,如果在被调方法中改变了值,也有可能会对调用者有影响吗?那到底什么时候会影响什么时候不会影响呢?

其实是不冲突的,之所以会有这种疑惑,是因为大家对于到底是什么是"改变值"有误解。

我们先回到上面的例子中来,看一下调用过程中实际上发生了什么?

怎么在Java中实现值传递和引用传递

在参数传递的过程中,实际参数的地址0X1213456被拷贝给了形参。这个过程其实就是值传递,只不过传递的值得内容是对象的应用。

那为什么我们改了user中的属性的值,却对原来的user产生了影响呢?

其实,这个过程就好像是:你复制了一把你家里的钥匙给到你的朋友,他拿到钥匙以后,并没有在这把钥匙上做任何改动,而是通过钥匙打开了你家里的房门,进到屋里,把你家的电视给砸了。

这个过程,对你手里的钥匙来说,是没有影响的,但是你的钥匙对应的房子里面的内容却是被人改动了。

也就是说,Java对象的传递,是通过复制的方式把引用关系传递了,如果我们没有改引用关系,而是找到引用的地址,把里面的内容改了,是会对调用方有影响的,因为大家指向的是同一个共享对象。

那么我们改变一下pass方法:

public void pass(User user) {
  user = new User();
  user.setName("hollischuang");
  System.out.println("print in pass , user is " + user);
}

再看一下整个过程中发生了什么: 

怎么在Java中实现值传递和引用传递

这个过程,就好像你复制了一把钥匙给到你的朋友,你的朋友拿到你给他的钥匙之后,找个锁匠把他修改了一下,他手里的那把钥匙变成了开他家锁的钥匙。这时候,他打开自己家,就算是把房子点了,对你手里的钥匙,和你家的房子来说都是没有任何影响的。

所以,Java中的对象传递,如果是修改引用,是不会对原来的对象有任何影响的,但是如果直接修改共享对象的属性的值,是会对原来的对象有影响的。

看完上述内容,你们掌握怎么在Java中实现值传递和引用传递的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

推荐阅读:
  1. JavaScript的值传递和引用传递
  2. Java中值传递和引用传递的案例

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:使用python怎么制作一个学生信息管理系统

下一篇:怎么在python中利用matplotlib制作一个双Y轴图

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》