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)虽然在赋值时只复制了其头部信息(包含指向底层数组的指针、长度和容量),但它仍然指向同一底层数组,因此可以认为是引用类型。
相关推荐
摇滚侠7 分钟前
MyBatis 入门到项目实战 特殊 SQL 的执行 34-37
java·sql·mybatis
phltxy37 分钟前
Spring AI 可观测性与 Zipkin 实战
java·人工智能·spring
兰令水44 分钟前
leecodecode【面试150】【2026.6.13打卡-java版本】
java·算法·leetcode
.道阻且长.1 小时前
C++ string 操作指南:接口解析
java·c语言·开发语言·c++
蚰蜒螟1 小时前
Java 对象的内存密语:从字段偏移量计算到 Unsafe 访问的完整链路
java·开发语言
IT 行者1 小时前
GitHub Spec Kit 实战(六):/speckit.implement 怎么用、怎么审、怎么发现 spec 阶段的遗漏——五部曲收官
java·驱动开发·github·ai编程·claude
星辰_mya1 小时前
CountDownLatch深度解析
java·开发语言·后端·架构
伊甸31 小时前
从企业级项目学敏感词过滤:DFA算法与双层缓存实战
java·算法·缓存
cfm_29141 小时前
JVM新一代垃圾收集器深度解析:G1与ZGC
java·jvm
x***r1511 小时前
.NET 10 SDK 安装教程(dotnet-sdk-10.0.100-win-x64详细步骤)
java·服务器·前端