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倍,但不影响最终输出结果,下面引入内存分析图进行解释:
如上图所示:在内存中,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中,只有值传递一种参数传递方式,在某些操作上,易产生混淆,误认为引用传递,实际传入的也是地址值,所以依然是值传递。