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)虽然在赋值时只复制了其头部信息(包含指向底层数组的指针、长度和容量),但它仍然指向同一底层数组,因此可以认为是引用类型。
相关推荐
移远通信2 小时前
短信的应用
java·git·python
a努力。2 小时前
阿里Java面试被问:WebSocket的心跳检测和自动重连实现
java·开发语言·python·websocket·面试·职场和发展·哈希算法
冷雨夜中漫步2 小时前
Python入门——__init__.py文件作用
android·java·python
deng12042 小时前
【排序算法总结(1)】
java·算法·排序算法
小宋10212 小时前
Kafka 自动发送消息 Demo 实战:从配置到发送的完整流程(java)
java·分布式·kafka
Remember_9932 小时前
【数据结构】Java数据结构深度解析:栈(Stack)与队列(Queue)完全指南
java·开发语言·数据结构·算法·spring·leetcode·maven
期待のcode2 小时前
JVM 中对象进入老年代的时机
java·开发语言·jvm
资深web全栈开发2 小时前
高并发的本质:超越语言的协作哲学——以 Go HTTP 服务器为例
服务器·http·golang·系统设计·goroutine·高并发架构·go并发
派大鑫wink2 小时前
【Day37】MVC 设计模式:原理与手动实现简易 MVC 框架
java·设计模式·mvc