我通常最终尝试每个组合,直到它编译.有人可以解释我应该在哪里使用?
Dan*_*ral 121
在一个方面,我不同意克里斯的 回答.该班Any
,AnyRef
和AnyVal
是类.但由于JVM的内在局限性,它们不会作为字节码中的类出现.
这是因为并非Java中的所有内容都是对象.除了对象之外,还有原语.Java中的所有对象都是后代java.lang.Object
,但原语被分开,目前*,程序员无法扩展.还要注意,基元有"运算符",而不是方法.
另一方面,在Scala中,一切都是对象,所有对象都属于一个类,并且它们通过方法进行交互.生成的JVM字节码并不反映这一点,但这并不会使它们变得那么简单,就像Java具有泛型一样,即使字节码没有它们.
因此,在Scala中,所有对象都是后代Any
,包括Java认为对象和Java认为原语的内容.在Java中没有等价物,因为没有这样的统一.
在Java中被认为是原始的所有内容都是AnyVal
Scala的后代.直到Scala 2.10.0 AnyVal
被封存,程序员无法扩展它.看看Scala在.Net上会发生什么应该会很有趣,因为互操作性本身要求Scala至少能够识别用户定义的"原语".
还延伸Any
就是AnyRef
,这相当于java.lang.Object
(在JVM上在任何速率).
截至斯卡拉2.9.x,用户不能延长Any
或AnyVal
,也不是从Java引用它们,但人,他们可以在Scala中被投入其他用途.具体来说,键入签名:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
Run Code Online (Sandbox Code Playgroud)
从类层次结构中,每个方法应该是显而易见的.值得注意的是,然而,就是f
和h
意志自动箱,但g
不会.这与Java所做的有点相反,f
并且h
无法指定,并且g
(定义为java.lang.Object
)会导致自动装箱.
但是,从Scala 2.10.0开始,用户可以扩展AnyVal
或Any
使用以下语义:
如果类扩展AnyVal
,在某些条件下不会在堆上为它创建实例.这意味着这个类的字段(在2.10.0上只允许一个字段 - 无论是否会改变还有待观察)将保留在堆栈中,无论它们是基元还是对其他对象的引用.这允许扩展方法没有实例化成本.
如果特征扩展Any
,那么它可以与扩展的AnyRef
类和扩展的类一起使用AnyVal
.
PS:在我看来,Java可能会遵循C#来允许"struct"原语,也许是typedef,因为并行性而不诉诸于它们并不能很好地实现性能.
Any
和AnyVal
是,我相信,阶的部分类型的系统和不阶级作为(在相同的方式Nothing
是一种类型的,而不是一个类)。您不能在Java代码中显式使用它们。
但是,在Java / Scala互操作中,接受Java的方法Object
将期望使用scala Any
/ AnyRef
。
您实际上在尝试做什么?