Go、Java 的值类型和引用类型对比

Go、Java 的值类型和引用类型对比

  • [值类型(Value Types)](#值类型(Value Types))
    • Go
    • Java
    • [Go 和 Java 中的数组区别](#Go 和 Java 中的数组区别)
      • [Java 中的数组是引用类型](#Java 中的数组是引用类型)
      • [Go 中的数组是值类型](#Go 中的数组是值类型)
  • [引用类型(Reference Types)](#引用类型(Reference Types))
  • 如何判断一个类型是值类型还是引用类型?

值类型(Value Types)

当进行赋值或函数调用时,会复制整个数据。常见的值类型包括:

Go

‌基本数据类型‌:如 int、float64、bool、string、complex64 等。

‌数组(Array)‌:如 3int

‌结构体(Struct)‌:由多个字段组成的复合类型。

这些类型在赋值或传递时会复制整个数据,因此修改副本不会影响原始数据。

Java

‌基本数据类型‌:如 int、Integer、String、char 等

Go 和 Java 中的数组区别

Java 中的数组是引用类型

示例代码

java 复制代码
public class ArrType {
    public static void main(String[] args) {
        int[] arr = {1,2,3};
        System.out.println("main:" + arr);
        addOne(arr);
        System.out.println("main:" + arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }

    public static void addOne(int[] arr) {
        System.out.println("addone:" + arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] + 1;
        }
    }
}

运行程序的结果

bash 复制代码
E:\code\go\go_java>javac ArrType.java

E:\code\go\go_java>java ArrType
main:[I@15db9742
addone:[I@15db9742
main:[I@15db9742
2
3
4

前3行中打印输出了 [I@15db9742 数组的地址都是一致,说明Java中的数组是引用类型,调用addOne 方法之后,数组的值都增加了1。

Go 中的数组是值类型

示例代码

Go 复制代码
package main

import "fmt"

func addOne(arr [3]int) {
	fmt.Printf("addOne:%p\n", &arr)
	for index, value := range arr {
		arr[index] = value + 1
	}
}

func main() {
	arr := [3]int{1, 2, 3}
	fmt.Printf("main:%p\n", &arr)
	addOne(arr)
	fmt.Printf("main:%p\n", &arr)
	for _, value := range arr {
		println(value)
	}
}

运行程序的结果

bash 复制代码
E:\code\go\go_java>go run arr_type.go
main:0xc00000e120
addOne:0xc00000e150
main:0xc00000e120
1
2
3

addOne 中输出的数组地址和main 中的不一致,函数调用的时候复制了一份数组传递了进去,增加1之后,操作的是复制的数组,主函数的数组的值并没有改变

将数组改成切片就是引用类型了,示例代码

Go 复制代码
package main

import "fmt"

func addOne(arr []int) {
	fmt.Printf("addOne:%p\n", arr)
	for index, value := range arr {
		arr[index] = value + 1
	}
}

func main() {
	arr := []int{1, 2, 3}
	fmt.Printf("main:%p\n", arr)
	addOne(arr)
	fmt.Printf("main:%p\n", arr)
	for _, value := range arr {
		println(value)
	}
}

运行程序的结果

bash 复制代码
E:\code\go\go_java>go run arr_type.go
main:0xc00000e120
addOne:0xc00000e120
main:0xc00000e120
2
3
4

main、addOne 函数输出的地址都是一致的0xc00000e120,调用addOne函数之后,数值增加了1

引用类型(Reference Types)

引用类型的数据存储的是指向底层数据的地址(或描述符),赋值或传递时复制的是这个地址,而不是数据本身。多个变量可以共享同一块底层数据。常见的引用类型包括:

‌切片(Slice)‌:如 \[\]int。

‌映射(Map)‌:如 mapstringint。

‌通道(Channel)‌:如 chan int。

‌接口(Interface)‌:如 interface{}。

‌函数(Function)‌:如 func()。

‌指针(Pointer)‌:如 *int。

这些类型在赋值或传递时,只复制引用(地址),因此对一个变量的修改会影响其他引用该数据的变量。

如何判断一个类型是值类型还是引用类型?

  1. 看是否发生深拷贝‌:如果赋值或传递时复制了整个数据结构,它是值类型;如果只复制了引用,则是引用类型。
  2. 看底层数据是否共享‌:如果多个变量指向同一块底层数据,那么它们是引用类型。例如,切片(slice)虽然在赋值时只复制了其头部信息(包含指向底层数组的指针、长度和容量),但它仍然指向同一底层数组,因此可以认为是引用类型。
相关推荐
Flynt2 小时前
Java 27 升级实测:默认值动得比新特性多,有个老参数会让 JVM 直接起不来
java·jvm·后端
Bs_MoneyMagnet2 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
星云API技术支持2 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
niucloud-admin3 小时前
JAVA V6 多商户商城 开发文档——job 计划任务开发
java·python·github
海宇AI4 小时前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化车抵贷核保网关
java·人工智能·架构·自动化
cfm_29145 小时前
单例模式详解
java
我叫张土豆5 小时前
本体论、DDD、SDD、TDD:AI 编程时代的四层认知栈
java·人工智能
白远山6 小时前
家政服务家政社区派单实战:调度系统架构设计与实现指南
java·开发语言·小程序·架构·需求分析
海南java第二人6 小时前
从诞生到回收:JVM对象生命周期与垃圾回收全链路解析
java
SL_staff6 小时前
JVS-Logic:从页面配置工具到企业级业务逻辑中枢的技术演进
java·算法·全栈