1.总述
Java中参数传递是值传递!!!(很重要)。
如果参数类型是原始类型,那么传过来的就是这个参数的一个副本,也就是这个原始参数的值,这个跟之前所谈的传值是一样的。如果在函数中改变了副本的值不会改变原始的值.
如果参数类型是引用类型,那么传过来的就是这个引用参数的副本,这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,而是改变了地址中的值,那么在函数内的改变会影响到传入的参数。如果在函数中改变了副本的地址,如new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以不会改变参数的值。
2.细述
参数类型:
-
实参:在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”,简称“实参
changeStr(str); //这里的str就是实参
-
形参:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数,简称“形参”
static void changeStr(String str) //这里的参数str就是形参
实参传递给方法:
就是通过方法的传递机制进行传递
-
值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数(复制,在函数中对参数进行修改不会影响到实际参数)、
复制的是参数的引用(地址值),并不是引用指向的存在于堆内存中的实际对象
-
引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。(传地址,会影响实际参数)
方法参数有基本数据类型、引用数据类型
-
基本数据类型string、int等类型,很明显这里的str并没有被改变,这里很明显的看到出来:java使用的是值传递
-
public static void changeStr(String str){ str="welcome"; } /*** * 主要是值传递 */ private static void changeStrDemo() { String str="1234"; changeStr(str); //这里的str就是实参 System.out.println(str); //输出1234,而不是welcome }
-
引用数据传递:
-
这里可以看到调用方法后user中的name属性的值改变了,但是实际上java传递参数还是通过值传递,这里之所以会有产生引用传递的错觉:
因为复制的是地址!!!
main方法中的user是一个引用(也就是一个指针),它保存了User对象的地址值,当把user的值赋给pass方法的user形参后,即让pass方法的user形参也保存了这个地址值,即也会引用到堆内存中的User对象。
上面代码中,之所以产生引用传递的错觉,是因为参数保存的是实际对象的地址值,你改变的只是地址值指向的堆内存中的实际对象,并没有真正改变参数,参数的地址值没有变。
Demo0315 demo0315 = new Demo0315();
User user = new User();
user.setName("张三");
user.setAge(18);
System.out.println("pass方法调用前,user=" + user.toString());
demo0315.pass(user);
System.out.println("pass方法调用后,user=" + user.toString());
public void pass(User user) {
user.setName("李四");
System.out.println("pass方法中,user = " + user.toString());
}
这里的输出:
pass方法调用前,user=User{name='张三', age=18}
pass方法中,user = User{name='李四', age=18}
pass方法调用后,user=User{name='李四', age=18}
一个生活化例子:
引用传递:
你有一把钥匙,当你的朋友想要去你家的时候,如果你直接把你的钥匙给他了,这就是引用传递。这种情况下,如果他对这把钥匙做了什么事情,比如他在钥匙上刻下了自己名字,那么这把钥匙还给你的时候,你自己的钥匙上也会多出他刻的名字。
值传递:
你有一把钥匙,当你的朋友想要去你家的时候,你复刻了一把新钥匙给他,自己的还在自己手里,这就是值传递。这种情况下,他对这把钥匙做什么都不会影响你手里的这把钥匙。
但是,不管上面哪种情况,你的朋友拿着你给他的钥匙,进到你的家里,把你家的电视砸了(这里就是改变了那个user中属性的值)。改变的不是那把钥匙(地址值),而是钥匙打开的房子(地址值对应的实际对象)。
但是为什么基本数据类型不是砸电视呢???
因为基本数据类型的复制的直接就是参数的值,引用数据类型复制的参数是数据的地址(在内存当中的地址),实际上,在引用数据类型传值的时候,复制的参数是没有改变的即地址没有改变(这就是典型的值传递)