Java语言中,有关于参数的传递方式只有一种:值传递!

1.值传递:方法形参接收的是一个数值(也就是源值的副本),并对其进行处理,所以源参数并没有发生改变。
2.引用传递:方法形参接收的是对象的地址值(也称之为引用),这种操作的结果会通过地址找到原参数进行的一些列操作,所以会影响最终的结果。

java中能作为参数进行传递的三种类型:1.基本数据类型 2.引用数据类型3.对象类型。

下面通过一系列简单的代码解释java中的参数传递方式:

  • 基本数据类型作为参数传递:
  • 相关代码:
/**
 * TestParameter用来测试基本类型参数传递
 * @author Administrator
 *
 */
public class TestParameter {
	    public static void main(String[] args) {  
	        int number = 1;  
	        System.out.println("OldNumber:"+number);  
	        changeNumber(1);  
	        System.out.println("NewNumber:"+number);  
	    }  
/**
 * 参数为int 类型,传入changeNumber方法中
 * @param num
 */
	    public static void changeNumber(int number){    
	    	number = number * 4; // num的值改变,并开辟了新的空间,与源值没关系
	    }  
	      
}

输出结果:OldNumber:1   NewNumber:1.在main方法中我们调用了changeNumber方法,并进行了参数传递;在方法内部将传入参数扩大4倍,但不影响最终输出结果,下面引入内存分析图进行解释:

java中的参数传递 java中参数传递的两种方式_堆内存

如上图所示:在内存中,number的数值为1,调用changeNumber方法,使number的值扩大4倍,但是与此同时,该方法开辟了一块新的存储空间,所以不会发生新值覆盖原值的情况。所以在输出时,由于作用域的关系,main中的number值还是原值。

  • 对象作为参数传递:
  • 相关代码:
/**
 * TestParameter用来测试对象类型参数传递
 * @author Administrator
 *
 */
public class TestParameter {
    public static void main(String[] args) {  
        Number n = new Number();  
        System.out.println("OldNamber:"+n.number);  
        changeValue(n);  
        System.out.println("NewNamber:"+n.number);  
    }      
/**
 * @param n
 */
    public static void changeNamber(Number  n){  
    	n.number=n.number*4;  
    }  
}  
class Number {   
    int number = 3;  
}

输出结果:OldaNumber:3   NewNumber:12。如上,声明引用Number n,并且使其指向堆内存中Number对象,在栈内存中,保存堆内存中对象的地址,然后将地址作为参数传入changeNumber()方法中,在方法操作参数变量时,直接通过地址,对堆内存中的对象进行了相关操作,在main方法中也是通过Number n 这个引用寻找堆内存中对应的对象,但是值已经被改变。所以我们可以得知在方法操作过程中,改变的仅仅是对象的内容,其引用并未改变。

  • 引用类型数据参数传递(String类 与 Array数组):相较于基本类型数据,二者均属于引用数据类型,存在于堆内存中。
  • 相关代码:
/**
 * TestParameter用来测试引用数据类型参数传递
 * @author Administrator
 *
 */
public class TestParameter {
	  public static void main(String[] args) {  
	        int[] array = {1,1,1};   //定义int类型数组,并进行静态初始化
	        String str = "Hello";  //自定义字符串  
	        System.out.println("Old:"+str+"\t"+Arrays.toString(array));  
	        change(str,array);  
	        System.out.println("New:"+str+"\t"+Arrays.toString(array));  
	    }  
	     //改变字符串和数组的方法  
	    public static void change(String str,int[] ch){  
	        str = "Hi";  
	        ch[0]=0;  //数组索引从0开始,代表第一个元素
	    }  
	}

输出内容: Old:Hello [1,1,1]  New: Hello [0,1,1]。如上:调用change()方法时,是将str和array[ ]的堆空间地址传入,并且在栈内存中开辟了新的地址创建变量(即副本)存放传入的地址,在方法中,执行str = “Hi”,等价于 str = new String("Hi");实际上是在堆内存中重新开辟了一块内存,用于创建一个新的对象存储Hi,并且将新内存地址赋值给str。

第二个参数传入的也是array[ ]的堆内存地址,方法中,对array[0]进行操作,实际上可以相当于  对象名.变量,即对地址指向的堆内存对象的属性直接操作,并没有改变其地址值,因此,在main方法中调用String str 和 int[ ] array还是指向的原地址的对象,str并没有修改,而array[ ]已经被修改。

总结:

在java中,只有值传递一种参数传递方式,在某些操作上,易产生混淆,误认为引用传递,实际传入的也是地址值,所以依然是值传递。