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)‌:如 [3]int

‌结构体(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)‌:如 map[string]int。

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

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

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

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

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

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

  1. 看是否发生深拷贝‌:如果赋值或传递时复制了整个数据结构,它是值类型;如果只复制了引用,则是引用类型。
  2. 看底层数据是否共享‌:如果多个变量指向同一块底层数据,那么它们是引用类型。例如,切片(slice)虽然在赋值时只复制了其头部信息(包含指向底层数组的指针、长度和容量),但它仍然指向同一底层数组,因此可以认为是引用类型。
相关推荐
码路飞3 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
SimonKing4 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员
Seven976 小时前
剑指offer-80、⼆叉树中和为某⼀值的路径(二)
java
怒放吧德德17 小时前
Netty 4.2 入门指南:从概念到第一个程序
java·后端·netty
雨中飘荡的记忆19 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
心之语歌21 小时前
基于注解+拦截器的API动态路由实现方案
java·后端
华仔啊1 天前
Stream 代码越写越难看?JDFrame 让 Java 逻辑回归优雅
java·后端
ray_liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·架构
Ray Liang1 天前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Java水解1 天前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端