您的位置:首页 > 产品设计 > UI/UE

call by value 和call by reference 部分转载 java 值传递 和 引用传递

2014-11-02 13:46 573 查看
关于JAVA中参数传递问题有两种,一种是按值传递(如果是基本类型),另一种是按引用传递(如果是對象).

首先以两个例子开始:

1)

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);

}

static void operate(StringBuffer x, StringBuffer y){

x.append(y);

y = x;

}

}

输出:AB,B

2)

public class Test2 {

public static void add3 (Integer i){

int val=i.intValue();

val += 3;

i = new Integer (val);

}

public static void main (String args [ ] ) {

Integer i = new Integer (0);

add3 (i);

System.out.println (i.intValue ( ));

}

}

输出: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). 基本类型

public class A{

public static void main(String[] args){

int x = 1;

System.out.println(x); //1

test(x);

System.out.println(x); //还是1==>By value

}

static void test(int a){

a = 2;

}

}

2). 引用类型

public class B{

public static void main(String[] args){

Integer x = new Integer(1);

System.out.println(x);

test(x);

System.out.println(x);

}

static void test(Integer a){

a = 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指向的对象。

有人说了数组。数组也是一个引用类型,它的参数传递方式按照引用类型的参数传递一样可以解释得通:

import java.util.Arrays;

public class A{

public static void main(String[] args){

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 test(int[] a){

a = new int[]{1, 2, 3}; //指向了新对象

}

static void test2(int[] a){

if(a != null && a.length > 0)

a[0]++; //修改原来的那个对象

}

}

对象是传引用(call by reference),简单类型是传值(call by value),不要被网上的一些概念所迷惑!!!你可以自己做个试验。

至于String等类型传的还是引用。如果你用concat方法,String对象的原值就会被改变。

但你如果按如下方法:

public class Test {

public static void test(String str) {

str = "World";

}

public static void main(String[] args) {

String string = "Hello";

test(string);

System.out.println(string);

}

}

  运行结果:Hello

这里str = "World" 就等同于 String str=new String("World")。所以结果没有改变!!!

下列程序在1处是否会有异常,如果没有,输出是什么?是否会运行到2处,如果会,输出是什么?为什么会有这样的结果?

  import java.util.arraylist;

   import java.util.list;

  

   public class testclass {

   public static void main(string args[]) {

     list list = new arraylist();

     test2(list);

     system.out.println(list.size()); // 1处

     test3(list);

     system.out.println(list.size()); // 2处

   }

  

   public static void test2(list list) {

     list = null;

   }

  

   public static void test3(list list) {

      list.add(“aaaa“);

   }

   }

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

// }

// }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: