前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >细说值传递、引用传递和地址传递

细说值传递、引用传递和地址传递

原创
作者头像
闫同学
发布2023-10-14 17:23:37
发布2023-10-14 17:23:37
2430
举报
文章被收录于专栏:扯编程的淡扯编程的淡

细说值传递、引用传递和地址传递

1 实参和形参

形式参数:是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传入的参数。

实际参数:在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”。

代码语言:go
复制
func main() {
   i := sum(2, 4) //2,4为实参
   fmt.Println(i)
}

func sum(a int, b int) int { //a,b为形参
   c := a
   return b + c //a,b,c为形参
}

2 值传递、引用传递和指针传递:

值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

引用传递:指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

指针传递:指在调用函数时将实际参数的指针地址直接传递到函数中,类似于引用传递,最大不同就是指针指向的类型不能为null。

指针传递和引用传递的不同:指针就是地址变量,所以引用相当于把地址常量作为参数,指针相当于把地址变量作为参数。

2.1 Go语言演示
代码语言:go
复制
type Obj struct {
   Id   int
   Name string
}

func main() {
	//值传递和引用传递测试
	fmt.Println("值传递...")
	v1 := 2
	v2 := Obj{2, "ls"}
	fmt.Println(v1, v2)
	updateVal(v1, v2)
	fmt.Println(v1, v2)

	//指针传递测试
	fmt.Println("指针传递...")
	v3 := 2
	v4 := Obj{2, "ls"}
	fmt.Println(v3, v4)
	updateValPoint(&v3, &v4)
	fmt.Println(v3, v4)
}

//值传递
func updateVal(v1 int, v2 Obj) {
   v1 = 1
   v2 = Obj{1, "zs"}
}

//引用传递
func updateValPoint(v1 *int, v2 *Obj) {
   *v1 = 12
   *v2 = Obj{1, "zs"}
}

输出:

代码语言:shell
复制
值传递...
2 {2 ls}
2 {2 ls}
指针传递...
2 {2 ls}
12 {1 zs}
2.2 Java语言演示
代码语言:java
复制
public static void main(String[] args) {
    System.out.println("值传递1");
    int v1 = 2;
    String v2 = "zz";
    Obj v3 = new Obj(2, "ls");
    System.out.println(v1 + "--" + v2 + "--" + v3);
    updateValue(v1, v2, v3);
    System.out.println(v1 + "--" + v2 + "--" + v3);

    System.out.println("值传递2");
    int v4 = 2;
    String v5 = "zz";
    Obj v6 = new Obj(2, "ls");
    System.out.println(v4 + "--" + v5 + "--" + v6);
    updateValuePoint(v4, v5, v6);
    System.out.println(v4 + "--" + v5 + "--" + v6);
}

public static void updateValue(int v1, String v2, Obj v3) {
    v1 = 1;
    v2 = "ww";
    v3 = new Obj(1, "zs");
    v3.setId(1);
    v3.setName("zs");
}

public static void updateValuePoint(int v1, String v2, Obj v3) {
    v1 = 1;
    v2 = "ww";
    v3.setId(1);
    v3.setName("zs");
}

@AllArgsConstructor
@ToString
@Data
static class Obj {
    public int id;
    public String name;
}

输出:

代码语言:shell
复制
2--zz--Main.Obj(id=2, name=ls)
2--zz--Main.Obj(id=2, name=ls)
2--zz--Main.Obj(id=2, name=ls)
2--zz--Main.Obj(id=1, name=zs)

3 总结下

在Java方法中参数列表有两种类型的参数,基本类型和引用类型。

基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。

引用数据类型:指针存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用。但是如果通过操作副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。(两个引用,同一个地址,任何修改行为2个引用同时生效)。

这两种类型都是将外面的参数变量拷贝一份到局部变量中,基本类型为值拷贝,引用类型就是将引用地址拷贝一份。

参考文章

https://www.cnblogs.com/lingyejun/p/11028808.html

https://blog.csdn.net/belongtocode/article/details/107713117

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 细说值传递、引用传递和地址传递
    • 1 实参和形参
    • 2 值传递、引用传递和指针传递:
      • 2.1 Go语言演示
      • 2.2 Java语言演示
    • 3 总结下
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档