You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Scala中Any与AnyRef的区别是什么?为何Int属AnyVal而String属AnyRef?

Scala中Any、AnyVal与AnyRef的区别解析

嘿,这个问题问得很到位,刚好戳中Scala类型系统的核心点,我来给你拆解清楚:

一、Any与AnyRef的核心区别

  • Any是整个类型系统的“根节点”:Scala里所有的类型——不管是值类型、引用类型,甚至是特殊的Null、Nothing——全部直接或间接继承自Any。它比Java的Object范围更广,因为Java的Object不涵盖基本数据类型,而Any把所有类型都揽入麾下。
  • AnyRef是引用类型的专属根:它对应Java里的Object,所有非值类型的引用类型(比如自定义类、集合、String等等)都继承自AnyRef。而和它并列的AnyVal,则是所有值类型的根。
  • Null的归属差异:Null是所有AnyRef类型的子类型,只能赋值给AnyRef变量;但Any可以接受Null、值类型、引用类型等所有类型的值,毕竟它是最顶层的父类。

二、为什么Int属于AnyVal,String属于AnyRef?

Int归为AnyVal的原因

Scala的AnyVal家族对应的是Java里的基本数据类型(int、double、boolean等)的“Scala包装”,但Scala在编译时会尽可能把它们优化成Java基本类型,以此提升性能。这些值类型都是不可变的,而且直接存储值本身,不是存储对象引用,所以被归类到AnyVal下。AnyVal包含的类型有Byte、Short、Int、Long、Float、Double、Char、Boolean,还有特殊的Unit(对应Java的void)。

就像你给出的示例:

val a: AnyVal = 3  // Int是AnyVal的子类型,完全合法

String归为AnyRef的原因

Scala里的String本质上就是Java的java.lang.String类,属于典型的引用类型——它存储的是对象的引用,而非直接存储字符串的值。所有这类基于对象的引用类型,都归属于AnyRef的子类型,所以你的示例里:

val b: AnyRef = "1" // String是AnyRef的子类型,赋值完全没问题

补充个反向验证的例子

如果反过来赋值就会编译报错,能更直观看到类型边界:

// val c: AnyRef = 3  // 编译错误:Int不是AnyRef的子类型
// val d: AnyVal = "1" // 编译错误:String不是AnyVal的子类型

内容的提问来源于stack exchange,提问作者Bin

火山引擎 最新活动