java中关于参数传递问题的解释(传值与传引用的若干问题的解释)

首先解释解释一下,关于Java参数传递的一些个人看法。

其实不论是Java中的8中基本数据类型通过直接复制值的方式传递,还是其他类型(包括自定义类型)通过所谓的引用传递,都是通过传递一个值,就是一个类型的拷贝(基本类型为直接复制值,引用方式通过复制地址的值)。


package cn.edu.nwsuaf.cie.qhs;


/**
 * 
 * @author 静寞小森(沧海森林)
 *
 */
public class ArgumentPassing {

	/**
	 * 此处,我们将通过程序进行分析Java中参数传递的几种常见情况、问题
	 * 通过以常见的swap(*,*)方法为例进行阐明
	 * 1.以swap()为例说明大家可能都比较头痛的全局变量的情况
	 * 2.以swap(int,int)为例说明网上经常谈到的通过传值方式传参的情况
	 * 3.以swap(class,class)为例说明网上经常谈到的通过传递引用传参的情况
	 * 	这里将class分为两种情况讨论,为了便于编程,分别采用了String类型和本类的自定义类型
	 * 	3.1 swap(String,String)
	 * 	3.2 swap(ArgumentPassing,ArgumentPassing)
	 * 4.以swap(int[],int pos1,int pos2)数组类型为例说明经常会误解的数组传参的情况
	 * 5.以实现Cloneable接口为例说明如何在对象传递时,只是传递其中的值
	 */
	
	private int num1 = 1;
	private int num2 = 2;
	
	public int getNum1() {
		return num1;
	}
	public void setNum1(int num1) {
		this.num1 = num1;
	}
	public int getNum2() {
		return num2;
	}
	public void setNum2(int num2) {
		this.num2 = num2;
	}
	/**
	 * 下面为使用全局变量情况的swap()
	 */
	public void swap(){
		int temp = this.getNum1();
		this.setNum1(this.getNum2());
		this.setNum2(temp);
	}
	/**
	 * 下面为以int为例传值传参情况的swap(int,int)
	 */
	public void swap(int num1, int num2){
		int temp = num1;
		num1 = num2;
		num2 = temp;
	}
	/**
	 * 下面为以String类型为例传引用传参情况的swap(String,String)
	 */
	public void swap(String str1,String str2){
		String tempStr = str1;
		str1 = str2;
		str2 = tempStr;
	}
	/**
	 * 下面为以ArgumentPassing自定义类型为例传引用传参情况的swap(ArgumentPassing,ArgumentPassing)
	 */
	public void swap(ArgumentPassing arg1,ArgumentPassing arg2){
		int num1 = arg1.getNum1();
		arg1.setNum1(arg2.getNum2());
		arg2.setNum2(num1);
	}
	/**
	 * 下面为以int[]数组类型为例传递参数情况的swap(int[],int pos1,int pos2)
	 */
	public void swap(int[] array,int pos1,int pos2){
		int temp = array[pos1];
		array[pos1] = array[pos2];
		array[pos2] = temp;
	}
	public String toString(){
		return "This object contains paramaters such as below: num1 = "+ this.getNum1()+";num2="+this.getNum2();
	}
	
	public void test(){
		ArgumentPassing argPassing = new ArgumentPassing();
		int num1 = 1;
		int num2 = 2;
		System.out.println("调用全局变量情况下的swap()方法之前:num1="+argPassing.getNum1()+";num2="+argPassing.getNum2());
		argPassing.swap();
		System.out.println("调用全局变量情况下的swap()方法之后:num1="+argPassing.getNum1()+";num2="+argPassing.getNum2());
		/**
		 * 运行结果为:
		 * 调用全局变量情况下的swap()方法之前:num1=1;num2=2
		 * 调用全局变量情况下的swap()方法之后:num1=2;num2=1
		 */
		System.out.println("******************************************************************************************");
		System.out.println("调用传值传参情况下的swap(int,int)方法之前:num1="+num1+";num2="+num2);
		argPassing.swap(num1, num2);
		System.out.println("调用传值传参情况下的swap(int,int)方法之后:num1="+num1+";num2="+num2);
		/**
		 * 运行结果为:
		 * 调用传值传参情况下的swap(int,int)方法之前:num1=1;num2=2
		 * 调用传值传参情况下的swap(int,int)方法之前:num1=1;num2=2
		 */
		/**
		 * 这里为什么会是这样的结果呢?
		 * 原因就在于其为传值传递,只是负责把num1,num2的值传递给参数列表中的对应位置,复制一个值给它,然后就和他们没有关系了。
		 * 所以即使是在函数体内,其对应的参数列表的参数值改变了,也和它(们)没有关系了。
		 */
		System.out.println("******************************************************************************************");
		String str1 = "This is str1";
		String str2 = "This is Str2";
		System.out.println("调用传递引用传参情况下的swap(String,String)方法之前:str1="+str1+";str2="+str2);
		argPassing.swap(str1, str2);
		System.out.println("调用传递引用传参情况下的swap(String,String)方法之后:str1="+str1+";str2="+str2);
		/**
		 * 运行结果为:
		 * 调用传递引用传参情况下的swap(String,String)方法之前:str1=This is str1;str2=This is Str2
		 * 调用传递引用传参情况下的swap(String,String)方法之后:str1=This is str1;str2=This is Str2
		 */
		/**
		 * 为什么呢?为什么结果却是这样子的?我们不是通过传递引用传递过来的吗?如果你是C++的程序猿或者对C++有着一定的了解,你一定纳闷,
		 * C++里引用这样就是可以的,可以交换的呀!为什么这里却是这样子的呢?不要着急,看下面的另一个通过引用来交换的例子。
		 */
		System.out.println("******************************************************************************************");
		ArgumentPassing arg1 = new ArgumentPassing();
		ArgumentPassing arg2 = new ArgumentPassing();
		System.out.println("调用传递引用传参情况下的swap(ArgumentPassing,ArgumentPassing)方法之前:arg1="+arg1.toString()+";arg2="+arg2.toString());
		argPassing.swap(arg1, arg2);
		System.out.println("调用传递引用传参情况下的swap(ArgumentPassing,ArgumentPassing)方法之后:arg1="+arg1.toString()+";arg2="+arg2.toString());
		/**
		 * 运行结果为:
		 * 调用传递引用传参情况下的swap(ArgumentPassing,ArgumentPassing)方法之前:arg1=This object contains paramaters such as below: num1 = 1;num2=2;arg2=This object contains paramaters such as below: num1 = 1;num2=2
		  *调用传递引用传参情况下的swap(ArgumentPassing,ArgumentPassing)方法之后:arg1=This object contains paramaters such as below: num1 = 2;num2=2;arg2=This object contains paramaters such as below: num1 = 1;num2=1
		 */
		/**
		 * 为什么结果是这样子的呢?为什么和上面的结果完全不一样呢?当然很好解释了。
		 * 因为Java中虽然是通过引用传递的,但是是传递的引用的副本(即将保存这个数据的地址复制了一份给参数(列表)),
		 * 然后如果只是像上面的swap(String,String)那样子交换的话,其实是改变了其参数列表中参数的指向(指针指向),却无法改变外边变量的值。
		 * 然后下面的这种就是讲参数列表中指向的地址中的内容进行了改变,如果没有改变的地方,很明显是没有变化的。
		 * 也就是说其实Java中的所谓的传递引用传递,其实根本就是传递了一份地址的值的拷贝,然后也可以说成是值传递。
		 */
		System.out.println("******************************************************************************************");
		int [] array = {1,2,3,4};
		int pos1 = 0;
		int pos2 = 1;
		System.out.println("调用数组传参情况下的swap(int[],int pos1,int pos2)方法之前:array[pos1]="+array[pos1]+";array[pos2]="+array[pos2]);
		argPassing.swap(array, pos1, pos2);
		System.out.println("调用数组传参情况下的swap(int[],int pos1,int pos2)方法之后:array[pos1]="+array[pos1]+";array[pos2]="+array[pos2]);
		/**
		 * 运行结果为:
		 * 调用数组传参情况下的swap(int[],int pos1,int pos2)方法之前:array[pos1]=1;array[pos2]=2
		 * 调用数组传参情况下的swap(int[],int pos1,int pos2)方法之后:array[pos1]=2;array[pos2]=1
		 */
		/**
		 * 这里的原因,有了上面所阐述的swap(ArgumentPassing,ArgumentPassing)结果的原因,以后就比较好理解了吧。其实数组传递,就是传递的数组的首地址的值,
		 * 然后传递了两个位置,就是将数组中的内容进行改变,这样一来,就是将指定地址中的内容值改变了,外边的数组参数内容自然就改变了。
		 */
		/**
		 * 大家可能比较纳闷,为什么还要说一说实现Cloneable接口呢?其实道理也是很简单的,因为有的时候,一个自定义类中包含另一个自定义类的对象,所以有时候我们不需要
		 * 改变对象中本来的值,只是拿来用一下,然后在其他地方改变或是修改什么的,这时候,要是直接使用=,就不是上策了,当然Java中也为我们想好了,这就是实现Cloneable接口。
		 * 其中只有一个方法clone,进行重写就可以了。
		 * 就不在详细说明了,只是提醒一下大家有这么个方式,遇到这类的问题,可以这么解决,有了这个方向,就很好找到这一类的资料,网上多的很呢。
		 */
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ArgumentPassing argPassing = new ArgumentPassing();
		argPassing.test();
	}
}


你可能感兴趣的:(java,编程,c,String,object,Class)