值传递与引用传递
值传递
-
是指在调用函数时,将一个参数传递给一个函数时,函数接收的是原始值的一个副本,只是实参和形参内容相同,但形参和实参是两个东西。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。
-
如下图,在值传递进行中,传递到函数中的是实参的符本,因此当函数改变实参时仅仅改变了实参的副本,实参并没有改变。
package com.zhou.partise;
public class Demo01 {
public static void main(String[] args) {
//值传递案例
int a = 1;
b(a);
System.out.println(a);//输出结果仍为1
}
public static int b(int c){
c = c+1;
return c;
}
}
- 通过源码可以看到,在下面图中,Integer以及int前面的修饰符都是被final所修饰的。(涉及到修饰符的概念和final的用法)
引用传递
-
传递的引用:是指在调用函数时,将实际参数的地址传递到函数中,那么在函数中对参数进行修改,将会影响到实际参数。
- 可以理解为将一个参数传递给一个函数时,形参复制了一份实参的地址(即此时形参和实参指向同一对象),但是实参和形参仍然是两个东西,不过此时他们指向的对象是相同的。
-
引用数据类型分为两个部分,引用变量和对象,这两个部分放在不同的地方,引用变量在方法栈中,而对象是放在堆内存中的,引用变量指向对象。
如下图所示,当传递参数之前会将参数进行复制,但是复制的是引用变量,复制后的引用变量还是指向内存中的同一对象,所以引用传递中,函数修改了参数会影响实际参数
package com.zhou.partise;
//标准类代码
public class Person {
private String name ;
private int age ;
public Person(){
}
public Person (String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.zhou.partise;
//测试类代码
public class Demo02 {
public static void main(String[] args) {
//引用传递例子
Person person = new Person("小周",6);
System.out.println(person.getName()+"---"+person.getAge());
System.out.println("=======================");
setPersonName(person);
System.out.println(person.getName()+"---"+person.getAge());
}
public static void setPersonName(Person p) {
p.setName("小李");
}
}
//输出结果
小周---6
=======================
小李---6
Process finished with exit code 0
String类型
- 值得注意的是,虽然String为引用类型,但是其无法进行进行引用传递。
package com.zhou.partise;
public class Demo03 {
public static void main(String[] args) {
int num = 10;
int1(num);
String str = "小周";
System.out.println(num); //输出仍然是10
System.out.println(str); //输出仍然是小周
}
public static void int1(int num) {
num = 99;
}
public static void string(String str) {
str = "小李";
}
}
- 主要是String类中字符串常量,一经定义就要入常量池,不再能改变,地址也是唯一的,之后再用还是这一地址,也就是即使声明三个不同的String变量,然后赋值同一个字符串常量,它们在内存中都是共用一个地址。