如何在Scala中创建AnyRef的现有Java类子类?

时间:2018-05-01 08:00:36

标签: java scala bytecode

Scala继承层次结构图:

Scala for the Impatient 一书中的上图显示所有Java类都是AnyRef类的子类。

  

图8-1显示了Scala类的继承层次结构。与Java中的基元类型对应的类以及类型Unit扩展AnyVal。所有其他类都是AnyRef类的子类,它是Java或.NET虚拟机中Object类的同义词。   AnyValAnyRef都扩展了Any类,即层次结构的根。

如何在不更改Java类的情况下实现这一目标?它是否在字节码级别处理?

2 个答案:

答案 0 :(得分:6)

免责声明:我绝不是Scala专家,但拥有20年的Java经验,包括JVM。

我的解释是句子

  

所有其他类都是 AnyRef类的子类,它是一个   Java 或.NET虚拟机中Object类的同义词。

(强调我的)完美地解释了它。

对于JVM,没有AnyRef类。文本将AnyRef称为同义词,而JVM没有这样的概念。因此,Scala编译器可能会将AnyRef的出现替换为java.lang.Object。当然,所有Java类都是java.lang.Object的子类,它们只是在Scala编译器中得到一个新名称,因此它们都是从AnyRef继承的(a.k.a。Object

我敢打赌你在任何Scala运行时JAR库中都找不到AnyRef.class条目,这意味着对于JVM来说,像AnyRef这样的类并不存在。

答案 1 :(得分:4)

这常常让初学者感到困惑。最近有一个very similar question on Software Engineering.SE。简单的答案是:MAGIC!

是的,真的。

Scala编译器不必遵守Scala语言的规则。从某种意义上说, Scala语言的规则!它必须实施和执行它们,但它不必遵循它们。而且它肯定不必遵循Java语言的规则。

因此,它的工作方式非常简单:每当某个Scala程序执行某些依赖于java.lang.String的行为就好像它是scala.AnyRef的子类时,它会生成一个行为就好像java.lang.Stringscala.AnyRef的子类。

那就是它。

您还可以询问Scala如何创建Java基元对象,这些对象是作为scala.AnyVal的子类的类的实例。或者,您可以问一下,当您在两个编辑器窗口中打开两个文件的源代码时,程序员如何看到两个类的私有实现,即使该语言表明您无法从中查看私有实现。外部。

原因总是一样的:因为您在语言之外,语言规则不适用于您。

从另一个方向来看,人们经常会问为什么他们可以从Java继承sealed类或调用声明为private[this]的方法。原因也是一样的:因为Java编译器不必使用Scala的规则。它甚至不会知道关于Scala规则的