如不了解形参与实参,请看博主9.java的实参和形参
值传递是指在调用函数时将实参复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实参。
详解:在方法的调用过程中,实参把它的实际值传递给形参,此传递过程就是将实参的值复制一份传递到函数中,这样如果在函数中对该值(形参的值)进行了操作将不会影响实参的值。因为是直接复制,所以这种方式在传递大量数据时,运行效率会特别低下。
引用传递是指在调用函数时将实参的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实参。
详解:引用传递弥补了值传递的不足,如果传递的数据量很大,直接复过去的话,会占用大量的内存空间,而引用传递就是将对象的地址值传递过去,函数接收的是原始值的首地址值。在方法的执行过程中,形参和实参的内容相同,指向同一块内存地址,也就是说操作的其实都是源数据,所以方法的执行将会影响到实际对象。
看下下面四个例子,深入了解java的值传递
public static void main( String[] args) {
ParamTest pt = new ParamTest();
int i = 10;
pt.pass(i);
System.out.println( "i is " +i);
}
public void pass(int j){
j = 20;
system.out.println( "j is " + j);
}
结果如下
j is 20
i is 10
public static void main(String[ ] args) {
ParamTest pt = new ParamTest();
User barry = new User();
barry.setName( "Barry");
barry.setGender("Boy");
pt.pass(barry);
system.out.println( "print in main , user is " + barry);
}
public void pass(User user) {
user.setName( "Ivory");
System.out.println( "print in pass , user is " + user);
}
结果如下
print in pass , user is User{name='Ivory', gender='Boy'}
print in main , user is User{name='Ivory' , gender='Boy'}
当我们在main中创建一个User对象的时候,在堆中开辟一块内存,其中保存了name和gender等数据。然后barry持有该内存的地址,比如说是ex123456。当尝试调用pass方法,并且barry作为实际参数传递给形式参数user的时候,会把这个地址ex123456交给user,这时,user也指向了这个地址。所以当user.setName时候,会在ex123456地址上进行操作,改变了实际参数的值。
public static void main( string[] args) {
ParamTest pt = new ParamTest();
string name = "Barry";
pt.pass(name ) ;
System.out.println( "print in main , name is " + name);
}
public void pass(string name) {
name = "Ivory";
system.out.println( "print in pass , name is " + name);
}
结果如下
print in pass , name is Ivory
print in main , name is Barry
我们在pass方法中使用name = “Ivory”;试着去更改name的值,实际上是直接改变了name的引用的地址。因为这段代码,会new一个String,在把引用交给name,即等价于name =new String(“Ivory”);。而原来的那个”Barry”字符串还是由实参持有着的,所以,并没有修改到实际参数的值。
public static void main(String[ ] args){
ParamTest pt = new ParamTest();
User barry = new User();
hollis.setName( "Barry");
hollis.setGender("Boy" );
pt.pass(barry);
system.out.println("print in main , user is " + barry);
public void pass(User user) {
user = new User();
user.setName( "Ivory");
user.setGender( "Girl");
system.out.println( "print in pass , user is " + user);
结果如下
print in pass , user is User{name='Ivory' , gender='Girl'}
print in main , user is User{name='Barry', gender= 'Boy'}
当我们在main中创建一个User对象的时候,在堆中开辟一块内存,其中保存了name和gender等数据。然后barry持有该内存的地址,比如说是ex123456。当尝试调用pass方法,并且barry作为实际参数传递给形式参数user的时候,会把这个地址ex123456交给user,这时,user也指向了这个地址。然后在pass方法内对参数进行修改的时候,即user = newUser();,会重新开辟一块内存,比如说是 ex456789,赋值给user。后面对user的任何修改都不会改变内存eX123456的内容。
上面这种传递是什么传递?肯定不是引用传递,如果是引用传递的话,在user=new User()的时候,实际参数的引用也应该改为指向ex456789,实际上并没有。这里是把实际参数的引用的地址复制了一份,传递给了形式参数。所以,上面的参数其实是值传递,把实参对象引用的地址当做值传递给了形式参数。
总结
Java中其实还是值传递的,只不过对于对象参数,值的内容是对象的引用。