一、基本数据类型
基本数据类型:调用 modify() 方法时,是从 实参 拷贝了一份数据 给形参;修改 形参 对 实参没有任何影响
import lombok.Data;
import lombok.experimental.Accessors;
public class TransferTest{
public static void main(String[] args) {
testInt();
}
private static void testInt(){
int i = 1;
System.out.println("调用前:int = " + i);//调用前:int = 1
modifyInt(i);
System.out.println("调用后:int = " + i);//调用后:int = 1
}
private static void modifyInt(int i1) {
i1 = 5;
}
}
二、引用数据类型
引用数据类型:调用 modify() 方法时,是从 实参 拷贝了一份数据的 引用 给形参;
import lombok.Data;
import lombok.experimental.Accessors;
public class TransferTest{
public static void main(String[] args) {
testInteger();
}
private static void testInteger(){
Integer integer = new Integer(1);
System.out.println("调用前:integer = " + integer);//调用前:integer = 1
modifyInteger(integer);
System.out.println("调用后:integer = " + integer);//调用后:integer = 1
}
private static void modifyInteger(Integer integer1) {
integer1 = 5;
}
}
三、引用类型:修改 形参 属性值 与 重新赋值
1、重新赋值
import lombok.Data;
import lombok.experimental.Accessors;
public class TransferTest{
public static void main(String[] args) {
testUser1();
}
private static void testUser1() {
User user = new User()
.setAgeInt(1)
.setAgeInteger(1);
System.out.println("调用前:user = " + user);
//调用前:user = User(ageInt=1, ageInteger=1)
modifyUser1(user);
System.out.println("调用后:user = " + user);
//调用后:user = User(ageInt=1, ageInteger=1)
}
private static void modifyUser1(User user1){
user1 = new User();
user1.setAgeInt(5)
.setAgeInteger(5);
}
}
@Data
@Accessors(chain = true)
class User{
private int ageInt;
private Integer ageInteger ;
}
- 引用类型 实参向形参传值时,复制了 对象的引用给形参;
- 重新给形参赋值,就是修改形参所存储的引用;
- 修改形参所存储的引用地址了之后,并不会影响实参引用的指向;
2、修改形参属性值
import lombok.Data;
import lombok.experimental.Accessors;
public class TransferTest{
public static void main(String[] args) {
testUser2();
}
private static void testUser2() {
User user = new User()
.setAgeInt(1)
.setAgeInteger(1);
System.out.println("调用前:user = " + user);
//调用前:user = User(ageInt=1, ageInteger=1)
modifyUser2(user);
System.out.println("调用后:user = " + user);
//调用后:user = User(ageInt=5, ageInteger=5)
}
private static void modifyUser2(User user1){
user1.setAgeInt(5)
.setAgeInteger(5);
}
}
@Data
@Accessors(chain = true)
class User{
private int ageInt;
private Integer ageInteger ;
}
由于引用类型,在传值时,传递的是引用;所以在未改变形参引用(未重新赋值)的情况下,修改形参的属性值,实参的属性值也会改变;
3、总结
通过 setter 方法修改属性值和重新赋值的区别:
setter:未修改形参的引用地址,故形参和实参所存储的引用相同;所以形参修改了,实参也会跟着修改;
重新赋值:重新赋值,意味着形参存储的引用地址变更了;形参跟实参的所存储的引用地址不再相同,所以形参任何操作都跟实参无关;
四、值传递和引用传递的区别
我的理解是:值传递和引用传递 一个重要区别是,值传递通过 拷贝 来传递,引用传递通过 共享 来传递;这也是为什么说 Java 不是引用传递的原因;
拷贝:Java 中 基本数据类型拷贝值,引用数据类型拷贝引用地址;修改形参不会对实参造成影响
共享:实参和形参共用同一块内存地址,形参修改,实参会同时被修改;
引用传递 猜想大致图解:
五、c++ 中值传递、指针传递、引用传递的区别
值传递
形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。
指针传递
我认为指针传递分为两种(猜想,如有误请指正):形参是指向实参地址的指针变量 和 形参是指向实参的 值 的地址的指针变量
1、形参是实参指向的地址的指针变量
2、形参是指向实参的 值 的地址的指针变量
Java 中引用数据类型的值传递 跟 这种指针传递类似(猜想,如有误请指正)
引用传递
形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。
六、愚见
- 值传递:是将 实参的值(值包括:基本数据类型的值和引用数据类型的地址),通过拷贝的方式传递给形参;
- 引用传递:是将实参的内存共享给形参,实参与形参患难与共(Java 为什么不是引用传递的原因)
- 指针传递:形参接收地址,实参可以传 本身的地址,也可以传 实参指针指向 的地址;猜想,如有误请指正)