Java call by value 和 by reference (值传递和引用传递)
来源:互联网 发布:javascript的dom对象 编辑:程序博客网 时间:2024/06/10 14:27
关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象).
首先以两个例子开始:
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午8:37:04 * */public class Test { public static void main(String[] args) { StringBuffer a = new StringBuffer("A"); StringBuffer b = new StringBuffer("B"); operate(a,b); System.out.println(a+","+b);//AB,B } static void operate(StringBuffer x,StringBuffer y){ x.append(y); y=x; }}
输出:AB,B
Test2
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午8:42:09 * */public class Test2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Integer i = new Integer(0); add3(i); System.out.println(i.intValue());//0 } private static void add3(Integer i) { // TODO Auto-generated method stub int val = i.intValue(); val += 3; i = new Integer(val); }}
输出:0
首先我们应该明白JAVA中的参数传递全是以值传递的。是基本类型,就拷贝一个基本类型传进方法;是引用,就拷贝一个引用变量传进去方法,理解了这 两点就能理解方法操作对象的相关问题了。最好能画出引用指向对象的图出来,就能完全理解了。
第1题,调用operate方法时,传入了两个引用a,b的拷贝x,y,这两个x,y都指向原a,b引用所指向的对象。x.append(y)对它指向的 对象(即a指向的对象)进行了操作。而x=y,只是两个拷贝变量在赋值,并没有影响到原b所指向的对象。所以b所指向的对象仍然为B。
第2题,i=new Integer(val)只是一个引用的拷贝指向了另外一个对象,而原来的i仍然是指向对象new Integer(0)的。
把握住了JAVA都是传值并且传的都是拷贝的话,类似的题大家都能迎刃而解了。
Java中的参数传递只有一种方式: by value. 理论说教太麻烦了,直接看些例子吧:
1). 基本类型
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午8:46:11 * */public class Test3 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int x = 1; System.out.println(x);//1 test(x); System.out.println(x);//1-------->by value } private static void test(int x) { // TODO Auto-generated method stub x = 2; }}
2). 引用类型
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午8:48:00 * */public class Test4 { public static void main(String[] args) { Integer x = new Integer(1); System.out.println(x);// 1 test(x); System.out.println(x);// 1 } private static void test(Integer x) { // TODO Auto-generated method stub x = new Integer(2); }}
理解这里的关键是区分对象和引用。 这里声明的x是一个引用,而不是一个对象(只是Java把它设计为看上去好像是对象一样)。这个引用它指向了一个对象,这个对象就是后面用new关键字生 成的对象。因此,可以说x指向了一个Integer对象。
在调用test方法的时候,程序将x作为参数传递给test方法了。这里仍然是值传递,在test调用过程中,会产生一份新的引用(不妨叫做y)。此 时,x和y指向了同一个对象。
x和y指向的是同一个对象, 由于Java的设计,我们可以通过操作引用来达到操作对象的目的。因此,如果我们此时使用y来修改对象的属性 (例如,y.someField++); 你可以看到x指向的对象同时也被修改到了。
另一方面,如果我们让y指向另外一个对象, y=new Integer(2); 此时x和y就指向了不同的
对象。y修改了它指向的对象的属性,很显然不会影响到x指向的对象。
有人说了数组。数组也是一个引用类型,它的参数传递方式按照引用类型的参数传递一样可以解释得通:
package com.whf.ByValue_ByReference;import java.util.Arrays;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午8:50:06 * */public class Test5 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int[] aa = {3,2,1}; System.out.println(Arrays.toString(aa));//[3, 2, 1] test(aa); System.out.println(Arrays.toString(aa));//[3, 2, 1] test2(aa); System.out.println(Arrays.toString(aa));//[4, 2, 1] } static void test2(int[] aa) { // TODO Auto-generated method stub if (aa!=null && aa.length>0) { aa[0]++; //修改原来对象 } } static void test(int[] a){ a = new int[]{11,12,13};// 指向了新对象 }}
对象是传引用(call by reference),简单类型是传值(call by value),不要被网上的一些概念所迷惑!!!你可以自己做个试验。
至于String等类型传的还是引用。如果你用concat方法,String对象的原值就会被改变。
但你如果按如下方法:
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午9:02:01 * */public class Test6 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String str = "Hello"; test(str); System.out.println(str); //Hello } private static void test(String str) { // TODO Auto-generated method stub str = "World"; }}
运行结果:Hello
这里str = “World” 就等同于 String str=new String(“World”)。所以结果没有改变!!!
下列程序在1处是否会有异常,如果没有,输出是什么?是否会运行到2处,如果会,输出是什么?为什么会有这样的结果?
package com.whf.ByValue_ByReference;import java.util.ArrayList;import java.util.List;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午9:04:11 * */public class Test7 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub List list = new ArrayList(); test2(list); System.out.println(list.size());//1处 (输出0) test3(list); System.out.println(list.size());//2处 (输出1) } private static void test3(List list) { // TODO Auto-generated method stub list.add("aaaaa"); } private static void test2(List list) { // TODO Auto-generated method stub list = null; }}
plumechen:
不会出错的。结果是0,1。
因为test2(list)传得是list的引用,我理解成指针置的副本,list=null;只是把那个传入的值设置为null,不改变原来 list的指针和内容。test3(list)传入的一样,但是执行了list.add()由于传入指针值的副本也指向原来的那个list的地址,所以原 来的那个list的内容就改变了,size变成了1了
6.下列正确的有()
A. call by value不会改变实际参数的数值
B. call by reference能改变实际参数的参考地址
C. call by reference不能改变实际参数的参考地址
D. call by reference能改变实际参数的内容
答案:ACD
Java中的参数传递只有一种方式: 值传递 (by value)
1、简单类型类型,在调用的方法中,直接是实参的一个拷贝
2、对象:程序将对象x作为参数传递给方法了。这里仍然是值传递,在方法调用过程中,会产生一份新的引用(不妨叫做y)。此时,x和y指向了同一个对象。
我们可以通过操作引用来达到操作对象的目的。 因此,如果我们此时使用y来修改对象的属性 (例如,y.someField++); 你可以看到x指向的对象同时也被修改到了。(值传递,在方法里产生引用,操作引用达到操作对象。所以引用可以修改实参(对象)的内容)
实验
package callbyvalue;//public class Test2 {//// public static void main (String [] args) {// StringBuffer a = new StringBuffer ("A");// StringBuffer b = new StringBuffer ("B");// operate (a,b);// System.out.println(a+","+b); //AB,B// }//// static void operate(StringBuffer x, StringBuffer y){ //JAVA中的参数传递全是以值传递的。// //是基本类型,就拷贝一个基本类型传进方法;是引用,就拷贝一个引用变量传进去方法// x.append(y); //x.append(y)对它指向的对象(即a指向的对象)进行了操作// y = x; //只是两个拷贝变量在赋值 并不会影响原来的对象// System.out.println(y); //AB// }// }//public class Test2 {//// public static void add3 (Integer i){// int val=i.intValue();// val += 3;// i = new Integer (val); //只是一个引用的拷贝指向了另外一个对象,而原来的i仍然是指向对象new Integer(0)的// }//// public static void main (String args [ ] ) {// Integer i = new Integer (0);// add3 (i);// System.out.println (i.intValue ( )); //0// }// }
我的实验
//public class Test2 { //我的实验//// public static void change (int i){// i=6; //给拷贝赋值,并没有改变a指向的值// }//// public static void main (String args [ ] ) {// int a=5;// change(a);// System.out.println (a); //5 JAVA都是传值并且传的都是拷贝的话// }// }//public class Test2 { //我的实验//// public static void change (int i){// i++; //对象是传引用(call by reference),简单类型是传值(call by value)// //传值(call by value)不会改变实际参数的数值// }//// public static void main (String args [ ] ) {// int a=5;// change(a);// System.out.println (a); //5 // }// }
Test8
package com.whf.ByValue_ByReference;/** * @author :辰 * E-mail: 15538323378@163.com * 创建时间:2017-3-24 上午9:17:16 * */public class Test8 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub int a = 8; change(a); System.out.println(a);//8 int x = 5; change1(x); System.out.println(x);//5 } private static void change1(int x) { // TODO Auto-generated method stub x++; } private static void change(int a) { // TODO Auto-generated method stub a =10; }}
参考地址:原文链接
- Java call by value 和 by reference (值传递和引用传递)
- call by value 和call by reference 部分转载 java 值传递 和 引用传递
- java中参数传递详解:call by value(按值传递)和 call by reference(按引用传递)
- Java 只有值传递(Pass By Value),没有引用传递(Pass By Reference)
- 值调用(call by value)和引用调用(call by reference)
- call by value 和 call by reference
- call by value 和call by reference
- call by value 和 call by reference
- Java call by value 和call by reference 的理解
- JAVA值传递(call by value)
- Java的传值(by value)和传引用(by reference)的讨论
- call by value 和 call by reference的区别
- call by value 和call by reference 部分转载
- call by value 和call by reference 部分转载
- call by value 和call by reference区别
- call by value 和call by reference 转载
- Java中参数以by value方式而非by reference 方式传递(值传递)
- java当中也有pass-by-value值传递或pass-by-reference地址传递吗
- thinkphp 分页出错 $page->render() 出错
- 「redis存储篇」string数据类型的操作
- Android中PopupWindow点击返回按钮关闭
- Lua中调用.和:的区别
- 关于异常EXCEPTION
- Java call by value 和 by reference (值传递和引用传递)
- ORA-01113,ORA-01110的简单解决
- java和matlab混合编程
- 射线
- 对象的浅拷贝
- 后台代码:大客户资料
- linux 命令\操作 备忘录
- CByteArray源码解析
- AngularJS实践与应用