Stackoverflow问答:Java是传值还是传引用?
译者注:这是一篇在Stackoverflow上面的一个经典问题,也是Java开发者容易混淆的一个问题,我节选了其中两个vote最高的回复进行翻译。
问题:我一直认为Java的参数是按引用传递,然而我看过一些文章里说Java的参数并不是按引用传递的,比如这篇,这让我很迷惑。Java中的参数到底是按引用传递还是按值传递?
在Java里参数是按值来传递的。比较难理解的可能是Java传递的是对象的引用,但这些引用是按值传递。
比如:
public static void main( String[] args ){ Dog aDog = new Dog("Max"); foo(aDog); if( aDog.getName().equals("Max") ){ //true System.out.println( "Java passes by value." ); }else if( aDog.getName().equals("Fifi") ){ System.out.println( "Java passes by reference." ); public static void foo(Dog d) { d.getName().equals("Max"); // true d = new Dog("Fifi"); d.getName().equals("Fifi"); // true
在这个例子里面,执行完foo()方法之后,在main方法里再调用aDog.getName()方法依然会返回”Max”,在main方法中的
aDog并没有因为foo()的执行而被重写,这说明了参数是按值来进行传递的。如果是按照引用来传递的话在执行完foo()
方法之后aDog.getName()将会返回”Fifi”。
就像这样:
Dog aDog = new Dog("Max"); foo(aDog); aDog.getName().equals("Fifi"); // true public void foo(Dog d) { d.getName().equals("Max"); // true d.setName("Fifi");
我刚刚发现你引用了我的文章 (译者注:这位是提问者引用文章的作者)
在Java的规范里说明了在Java中一切参数都是按值传递的,根本就没有引用传递这一说。
理解这个概念的关键是要明白
Dog myDog;
这里声明的并不是一个Dog对象,而是一个指向Dog对象的指针。
这是什么意思呢,就是当你执行
Dog myDog = new Dog("Rover"); foo(myDog);
本质上是你把创建好的Dog对象的地址传递给foo方法。(我说的‘本质上’其实是因为Java中的指针并不是直接的地址,不过可以简单的理解成这样)。
假设Dog对象在内存中的地址是42。那我们就是把42这个值传递给了foo方法。
如果foo方法的定义如下:
public void foo(Dog someDog) { someDog.setName("Max"); // AAA someDog = new Dog("Fifi"); // BBB someDog.setName("Rowlf"); // CCC
让我们来看看执行的时候会发生些什么。
1. someDog的值设置为42。
2. 在AAA行
a.someDog指向一个内存地址为42的Dog对象。
b.把Dog(内存地址为42)对象的name属性改为Max。
3. 在BBB行
a.一个新的Dog对象被创建,我们假设它的内存地址是74。
b.把这个74的内存地址值赋给someDog。
4. 在CCC行
a.someDog指向一个内存地址为74的Dog对象。
b.把Dog(内存地址为74)对象的name属性改为Rowlf。
5. 方法执行完毕。
现在让我们来想想在这个方法外面发生了什么:
myDog改变了吗?
这个问题的关键在于:
要明确myDog是一个指针,而不是一个实际的Dog对象。所以答案是它没有改变,myDog的值还是42;它指向的还是最开始的那个Dog对象(虽然在foo方法中的AAA行把它指向对象的name属性改成了Max,但是它指向的还是那个最初的Dog对象)。
这验证了改变所指对象的属性,但没有改变其指向。
Java的运行机制跟C很像。你可以给一个指针赋值,然后把这个指针传递给一个方法,之后在这个方法中你可以改变这个指针指向对象的数据,但是你不能改变这个指针的指向。
在C++,Ada,Pascal以及其他支持引用传递的语言中你可以直接改变传递的参数。如果Java是引用传递的话,那么在执行上面定义的foo方法的BBB行的时候someDog的指向就会被改变。
可以把引用参数当成被传递参数的别名,当这个别名被赋值的时候就相当于被传递的参数被赋值。
这对你有帮助吗?(我会把这个回答补充到我的文章里面去)。
jsp中js使用jQuery封装好的 $.ajax()方法与服务器进行交互 var jsonStick = this.strtoJson();
相关文章
- 【JAVA】Eclipse中开启java和xml智能提示功能(图文,已解决!)
- 大杂烩 -- Java内存布局【图】以及java各种存储区【详解】
- Java反编译生成java文件
- CSDN日报191016:Java纯干货分享:史上最全的JAVA工程师面试题汇总
- Java详解,java后端应届生面试题
- 全网最全的 Java 各类技术栈架构图汇总(建议收藏)
- java在Linux执行命令Java在Windows执行命令
- 记录Java的垃圾回收机制和几种引用
- java service
- 34 异常机制 异常体系结构 Java把异常当做对象来处理 并定义一个基类java.lang.Throwable作为所有异常的超类 Error Exception
- 【Java】Eclipse的安装和JDK的安装与配置教程
- 《Java EE 7精粹》—— 第2章 Servlets 2.1 WebServlet
- Java IDEA中设置导入import java.xx.*和设置导入具体的import java.xx.yy;
- IntelliJ IDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
- java实现 阿拉伯数字转换为汉字数字 算法
- JAVA面向对象设计中类关系
- JAVA反射学习网摘
- java基础day13---引用数据类型
- Java学习-050-AES256 之 java.security.InvalidKeyException: Illegal key size or default parameters 解决方法
- 数据源引用 java:/comp/env
- 深入理解Java中的final关键字
- java (Spring) 控制器中返回图片(验证码需求)
- Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法[转]
- 将英文字母正序逆序打印显示在屏幕上(java)
- How to improve Java's I/O performance( 提升 java i/o 性能)
- Java_jvisualvm使用JMX连接远程机器(实践)
- Java之final关键字详解
- 【JAVA】浅谈java枚举类