java--值传递和引用传递的区别详解

  关于方法的值传递和引用传递的区别和实际运用中的灵活运用,是不少初学者的一块硬骨头,刚开始自己也是似懂非懂,但随着JAVA基础知识的步步深入,和自己的不懈思索,对这个问题感觉"大彻大悟"了,而且似乎有了比较清析的表述思路,今天就把自己的成果展示给大家,希望能够对大家有所帮助,如果写的不好,还请见谅.

  其实,从本质上来讲,当一个方法调用另一个方法时,调用者的空间会保持不动,一个方法所接收的,永远是一个复本,例如:main 方法中inta=12,int[]b=new int[]{1,2,3},当它们被传递给另一个方法时,无论被main调用的方法怎么折腾,都不会影响到main方法的变量a,b的值.请看代码.

public class Test {		
	public static void main(String[] args) {
		int a=1;
		System.out.println("Before method intTest, a="+a);
		intTest(a);
		System.out.println("After intInput method,a="+a);
		
		int[] b=new int[]{1,2,3};
		System.out.println("Before arrTest,b="+b);
		arrTest(b);
		System.out.println("After intInput method,b="+b);
		
	}
	
	public static void intTest(int a){
		a=3;
		System.out.println("In intInput method , a="+a);
	}
	
	public static void arrTest(int[] b){
		b=new int[]{3,4,5};
		System.out.println("In arrInput method,b="+b);
	}
}


程序的输出结果如下:



  其中,变量b是一个引用变量,(所谓引用变量,形像的讲就是这个变量放了一条密码,这条密码能够打开一个独立存在的文件),其存储的是一条密码,通过这条密码能够打开并操作对应的数组,数组放在独立于main方法的另外一个区域.


  可以看出,main 方法很有原则,它不会把自己的文件原件(如变量a)给要调用的方法,而是复印一份副本(a的值)让它调用的方法拿去用,当方法执行完毕这个副本随即销毁,而原件在main那原封不动,未经过任何更改,随便你在复印件上写写画画(把a的值改为3).


  但是,问题在于,当这个副本里包含一条密码(变量b)的时候,被main调用的方法arrTest就会通过这个密码去打开并修改密码所对应的文件,当main再去利用b调用对应的文件的时候,就会发现,文件被arrTest修改了,因为给它的副本里有自己用得着的文件的密码,它正是用这个密码来修改文件的.看代码.

public class Test {		
	public static void main(String[] args) {
		int[] b=new int[]{1,2,3};
                System.out.println(b);
                System.out.println("Before arrTest array b is ");
		for(int i=0;i<b.length;i++){
			System.out.print(b[i]+ " ");
		}
		System.out.println();
		
		arrTest(b);
		
		System.out.println("After intInput array b is");
		for(int i=0;i<b.length;i++){
			System.out.print(b[i]+ " ");
		}
		System.out.println();
	}

        public static void arrTest(int[] b){
		for(int i=0;i<b.length;i++){
			b[i]=1;
		}
	}
}
  程序输出结果如下:



当main方法调用arrTest方法时,它把自己用得着的文件(即数组{1,2,3})的密码(即变量b的值 [I@2c1e6b )复制给了arrTest,而arrTest拿着这个密码对文件作了修改,当执行完arrTest执行完毕,main方法会发现文件竟然被改动了.看示意图.


1.调用arrText前


2.调用arrTest时



3.调用后


从中可以看出,main 方法把引用变量的值b复制给arrTest时,把对象的访问和修改权限赋给了arrTest,,而值传递a传递的仅仅是复制值,此值仅参与arr的运算,并未有任何其他含义,而此复制过程当然不会影响main方法的数据域,因为是main方法送出的只是复件呀.


最后讲一点,有的人理解值传递和引用传递的区别是值传递不会改变原数据域,引用传递会改变原数据域,真的是这样吗?如果你理解我上面所讲的内容,就会立即反应过来这种说法是错误的.请看代码.

public class Test {		
	public static void main(String[] args) {
		
		int[] b=new int[]{1,2,3};
		System.out.println(b);
		 System.out.println("Before arrTest array b is ");
			for(int i=0;i<b.length;i++){
				System.out.print(b[i]+ " ");
			}
		System.out.println();
		System.out.println();
			
		arrTest(b);
		
		System.out.println(b);
		System.out.println("After intInput method,b is");
		for(int i=0;i<b.length;i++){
			System.out.print(b[i]+ " ");
		}
		System.out.println();
		
	}
	
	public static void arrTest(int[] b){
		b=new int[]{3,4,5};
		System.out.println("In arrInput method,b="+b);
		System.out.println();
	}
}


程序输出结果如下:


虽然main 方法中的b是一个引用变量,但执行过arrTest方法后,b的所引用的数组内容仍然未变,为什么呢?











--------因为arrTest接收到b的值,即数组的地址值后,并未利用其访问并修改数组,而是对自己的变量b进行了一次重新赋值,main方法传的地址值被舍弃了,也就相当于arrTest放弃了修改b的权限,此次传值除了应和arrTest方法的格式让其正常执行外,基本相当于无效传值,arr要求main方法给传一个引用地址值才会执行,结果它获得这个地址值后却直接丢弃了,真是多此一举,直接在方法体内声明一个int[] b并自己给其赋值,将参数列表设为空不就得了嘛

猜你喜欢

转载自blog.csdn.net/u011193276/article/details/12956471