java引用与参数传递
来源:互联网 发布:道路横断面效果图软件 编辑:程序博客网 时间:2024/06/06 04:54
网上都在讲参数传递是一种拷贝,拷贝的变化不会影响原值,当然这是对的。还有一种说法,叫JAVA里只有一种参数传递方式,值传递,这也是对的。但是我总觉得这些说法容易让新人犯迷糊,因为有一个很常见的现象,很多时候拷贝也能改变原始对象的属性。所以有些人又把参数传递跟基本类型传递分开去解释这个问题,拆开显然是不对的。
先来看这段非常简单的代码:
package main;public class Main {public static void main(String[] args) {TestObject a = new TestObject();TestObject b = new TestObject();System.out.println(a); //打印结果为:main.TestObject@15db9742System.out.println(b); //打印结果为:main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:falseSystem.out.println(b.testString);//打印结果为:no.0a = b;System.out.println(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:truea.testString = "no.1";System.out.println(b.testString); //打印结果为:no.1}}package main;public class TestObject {public String testString = "no.0";}
使用 TestObject a = new TestObject(); 的时候,这个a,事实上就是一个引用(可以理解为C语言中的指针,是一个指向堆中真实对象的地址)。
所以,很自然,如果a 和 b 两个引用相同(指向同一个对象),运行a.testString = "no.1"之后,通过b获得的对象也改变了。
接下来我们看参数传递:
package main;public class Main {public static void main(String[] args) {// TODO 自动生成的方法存根TestObject a = new TestObject();TestObject b = new TestObject();System.out.println(a); //打印结果为:main.TestObject@15db9742System.out.println(b); //打印结果为:main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:falseSystem.out.println(b.testString);//打印结果为:no.0a = b;System.out.println(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:truea.testString = "no.1";System.out.println(b.testString); //打印结果为:no.1//------------------------------------------------------System.out.println(a);//打印结果为 :main.TestObject@6d06d69cchange(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b.testString);//打印结果为 :no.2}private static void change(TestObject s) {// TODO 自动生成的方法存根System.out.println(s);s.testString = "no.2";}}package main;public class TestObject {public String testString = "no.0";}
再来看这样的参数传递:看结果,最终,s改变了吗?s改变了,s变成了main.TestObject@7852e922。那a变了吗?a没有变,a还是main.TestObject@6d06d69c。s是不是拷贝?当然是拷贝,s变了,但是a没有改变。
package main;public class Main {public static void main(String[] args) {// TODO 自动生成的方法存根TestObject a = new TestObject();TestObject b = new TestObject();System.out.println(a); //打印结果为:main.TestObject@15db9742System.out.println(b); //打印结果为:main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:falseSystem.out.println(b.testString);//打印结果为:no.0a = b;System.out.println(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(a.equals(b)); //打印结果为:truea.testString = "no.1";System.out.println(b.testString); //打印结果为:no.1//------------------------------------------------------System.out.println(a);//打印结果为 :main.TestObject@6d06d69cchange(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b.testString);//打印结果为 :no.2//------------------------------------------------------System.out.println(a); //打印结果为 :main.TestObject@6d06d69cchange2(a);System.out.println(a); //打印结果为 :main.TestObject@6d06d69cSystem.out.println(b.testString);//打印结果为 :no.3}private static void change(TestObject s) {System.out.println(s); //打印结果为 :main.TestObject@6d06d69cs.testString = "no.2";}private static void change2(TestObject s) {System.out.println(s);//打印结果为 :main.TestObject@6d06d69cs.testString = "no.3";TestObject c = new TestObject();s = c;System.out.println(s);//打印结果为 :main.TestObject@7852e922s.testString = "no.4";System.out.println(s.testString);//打印结果为 :no.4}}package main;public class TestObject {public String testString = "no.0";}
其实,当s是main.TestObject@6d06d69c的时候,通过s.testString = "no.3";改变s指向的对象的属性的时候,a,b,s由于指向了同一个对象,所以看起来a也变了。当s变为main.TestObject@7852e922的时候,由于s和a,b已经不再指向同一个对象了,所以,s变了,a,b指向的对象不会有改变。
基本类型就不讲了,网上都是讲基本类型的参数传递拷贝不变性的。总结一下:
1.参数传递是拷贝,没问题。
2.JAVA里面的传递只有一种,值传递,没问题。
3.通过引用去改变堆中对象属性的时候,只要通过一个引用改变指向对象的属性,指向同一个对象的所有引用,看起来都会变。所以有时候看起来,方法内和方法外的引用一起改变了。
所以,在JAVA编写过程中,尽量不要使用public属性,而是要使用get,set方法。因为如果在你的函数中,通过引用改变了一些类的属性,就会使得程序变得混乱而不可读。为了后期维护的方便,请不要直接在调用的方法中通过引用改变引用指向对象的属性。
于此同时,克隆也是一样的道理,浅克隆中,克隆的对象如果存在引用,将会使得调用出现异常,因为两个克隆对象中如果拥有同一个引用属性,当你调用这个引用的时候,就会出现克隆的属性一起改变的情况,克隆的两个对象确实是两个对象,但是他们的引用属性却指向了同一个对象。如果他们指向的对象无法被修改,那么浅克隆完全是符合要求的。但是如果要通过这个引用去修改指向的那个对象,这其实是一定程度上违反了JAVA的基本原则(对扩展开放,对修改关闭)。
阅读全文
0 0
- java引用与参数传递
- java中的参数传递与引用
- <Java>函数参数值传递与引用传递
- java程序中参数值传递与引用传递问题
- string与参数引用传递
- string与参数引用传递
- string与参数引用传递
- java参数传递(传值与引用)
- 参数传递(值传递与引用传递)
- Java中函数参数的值传递与引用传递问题
- Java语言中的方法参数——值传递与引用传递
- 基本数据类型参数传递与引用数据类型参数传递区别
- 基本数据类型参数传递与引用型数据类型参数传递
- java参数与引用
- JAVA中参数传递(按值传递和引用传递)
- Java中的值传递和引用传递(参数传递)
- java参数传递(值传递还是引用传递)
- Java参数传递:值传递和引用传递
- 禁止按钮多次点击的方法
- Retrofit源码解析
- Spring中aop概念以及用法
- 【Java_SE】作业练习1105
- ThreadPool
- java引用与参数传递
- 餐饮界的黑科技 餐厅厨房小票打印机趣味玩法
- C#调用RDP,实现远程桌面共享及控制
- 对象的克隆——原型模式(一)
- 对于加密证书的理解
- MVC 接收url地址传参
- 慕课网——PHP进阶篇(类与面向对象6—10)
- SVN版本控制使用导向
- jquery新手入门教学(一)