一、传递类型
我们从c语言开始学习程序设计语言时就知道,参数的传递类型一般有两种:值传递和引用传递。那么什么是值传递什么是引用传递呢? 值传递:指在调用方法时将实际参数的值拷贝一份传递给方法,这样方法在修改参数的值时就不会影响到实际的值。 引用传递:指将实际参数的引用地址直接传递给方法中,这样在方法中如果通过该地址修改数据会影响到实际地址的值。 值传递和引用传递最大区别在于是否进行了拷贝。显而易见,如果没有进行拷贝则方法中对参数的操作肯定会影响到实际的值;但是进行了拷贝就一定不会影响实际值了吗? 接下来就要说说Java中的传递机制了。
二、Java传递机制
Java中普通数据类型的传递机制是值传递。下面我们通过几段代码进行说明。
package com.ring2.parameter; public class ValueTransfer { private static int i = 5; public static void test(int j) { j = 10; System.out.println("j = "+j); } public static void main(String[] args) { ValueTransfer.test(i); System.out.println("i = " +i); } }
下面是运行结果:
从结果上可以看出在对基本数据类型进行操作测试时是没有影响到实际的值的,故这里采用了值传递的机制。下面我们再看看传递引用类型会是什么结果:
package com.ring2.parameter; public class ReferenceTransfer { public static void test(Ring2 ring2) { ring2.setName("ring3"); } public static void main(String[] args) { Ring2 ring2 = new Ring2(); System.out.println(ring2.getName()); ReferenceTransfer.test(ring2); System.out.println(ring2.getName()); } } class Ring2 { private String name = "ring2"; public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
以下是运行结果:
可以看到,这里通过传递的参数改变了实际地址的值。那么Java到底是怎样的传递机制呢?是基本数据类型进行值传递,引用类型进行过引用传递吗?接下来我们再看看下一个例子就知道了:
package com.ring2.parameter; public class ReferenceTransfer { public static void test(Ring2 ring2) { ring2 = new Ring2(); //仅仅多出了这一行 ring2.setName("ring3"); } public static void main(String[] args) { Ring2 ring2 = new Ring2(); System.out.println(ring2.getName()); ReferenceTransfer.test(ring2); System.out.println(ring2.getName()); } } class Ring2 { private String name = "ring2"; public void setName(String name) { this.name = name; } public String getName() { return this.name; } }
这段代码和上一段相比仅仅是加了一行代码,ring2 = new Ring2(); 那么这一行代码能说明什么问题呢? 我们可以这样思考,如果Java采用的是基本类型值传递,引用类型引用传递;那么这时应该采用的是引用传递,引用传递不拷贝值,那么执行 ring2 = new Ring2() 这段代码,会把ring2重新引用到堆中新创建的Ring2类型的对象引用。那么就应该改变name为ring3,而结果却不是这样的,结果显示还是为ring2。 下面我来说说为什么如此: Java中采用的是值传递机制,会将实参的值拷贝一份给方法,而实参类型如果是引用类型同样也会拷贝实参的引用地址到方法中。所以说,Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。
总结:
首先Java中所采用的方法传递机制为:值传递
无论方法的形参中是基本数据类型还是引用类型,都会在调用方法时将实参的值拷贝一份给形参。
而区别在于基本数据类型是将值拷贝一份,在方法体内修改不会影响实参的值;而将引用类型的值是将引用进行拷贝,我们知道引用是指向的堆空间中的对象,通过这个引用我们可以修改对象中的属性如:person.age = 5;则person的年龄就变成了5,但是如果像这样:person = new Person();则是新建一个Persion对象,然后将Person对象的地址赋值给拷贝而来的person引用。同理:如果做过一些笔试题则会看到如果将String、Integer等这样的引用类型在方法体内做了改变如:str = “hello”;实参中的str并不会改变。这是因为这种做法相当于person = new Person()
; 会将“hello”字符串指向形参中的str。没错:这也是一个赋值语句,将右边的“hello"字符串赋值给”复制“来的str引用。所以实参中的str并不会改变。