Why can AnyVal be converted to AnyRef at runtime in Scala?

The following code can be compiled without errors.

val a: Int = 1 val b = a.asInstanceOf[AnyRef] 

This bothers me because Int extends AnyVal, which is not a subclass, but a sibling of AnyRef.

However, if attribution is used as follows:

 val a: Int = 1 val b: AnyRef = a 

This does not work.

 error: type mismatch; found : Int required: AnyRef Note: an implicit exists from scala.Int => java.lang.Integer, but methods inherited from Object are rendered ambiguous. This is to avoid a blanket implicit which would convert any scala.Int to any AnyRef. You may wish to use a type ascription: `x: java.lang.Integer`. val b: AnyRef = a 

What I understand:

asInstanceOf is executed at runtime, it causes the compiler to assume that val a is AnyRef. However, when ordering at compile time, the conversion cannot pass the type check, so we have a "type mismatch" error.

My questions:

  • Basically, why does conversion work at run time?
  • If AnyRef is considered java.lang.Object in the JVM, what about AnyVal? Is this an object at runtime?
    • (If so, what type is it? Java.lang.Object? But AnyVal is the brother of AnyRef, right?)
    • (If not, how can we use some subclass of AnyVal as Object, for example Int, Double)
    • Are there any tricks from the scala compiler?
+5
source share
2 answers

This is due to autoboxing:

 scala>val a: Int = 1 a: Int = 1 scala> a.getClass res2: Class[Int] = int scala> val b = a.asInstanceOf[AnyRef] b: AnyRef = 1 scala> b.getClass res1: Class[_ <: AnyRef] = class java.lang.Integer 

by calling conversion to AnyRef ( java.lang.Object ), you run autoboxing from int to java.lang.Integer

If AnyRef is considered as java.lang.Object in the JVM, what about AnyVal ? Is this an object at runtime?

AnyRef indeed an alias for java.lang.Object AnyVal is a "virtual" type; it exists only at compile time to complete the type system.

At run time, instances that extend AnyVal are converted to the corresponding native type ( int , double , etc.), with the exception of String , which goes into java.lang.String , which itself extends java.lang.Object , but has special processing in the JVM.

But AnyVal is the brother of AnyRef , right?)

Both AnyVal and AnyRef extend the type of Any , but do not extend each other.

Are there any tricks from the scala compiler?

Loads :)

For a more complete explanation of a poem like scala, I suggest you start by reading: http://docs.scala-lang.org/tutorials/tour/unified-types.html

+4
source

In addition to “because of autoboxing,” you can watch what magic is used.

-Xprint:all will show what phase the compiler did the magic.

-Ytyper-debug shows what decisions typer made.

For example, if val a: Int , then val b = a.isInstanceOf[AnyRef] changes to Int.box(a).$asInstanceOf[Object] in erasure, where $asInstanceOf is the nominal member of Object .

There is a good comment about these transformations in erasing :

 /** Replace member references as follows: * * - `x == y` for == in class Any becomes `x equals y` with equals in class Object. * - `x != y` for != in class Any becomes `!(x equals y)` with equals in class Object. * - x.asInstanceOf[T] becomes x.$asInstanceOf[T] * - x.isInstanceOf[T] becomes x.$isInstanceOf[T] * - x.isInstanceOf[ErasedValueType(tref)] becomes x.isInstanceOf[tref.sym.tpe] * - xm where m is some other member of Any becomes xm where m is a member of class Object. * - xm where x has unboxed value type T and m is not a directly translated member of T becomes T.box(x).m * - xm where x is a reference type and m is a directly translated member of value type T becomes x.TValue().m * - All forms of xm where x is a boxed type and m is a member of an unboxed class become * xm where m is the corresponding member of the boxed class. */ 

In contrast, the conversion due to the link mentioned in the OP error message is due to implicit in Predef :

 scala> val I: java.lang.Integer = a [[syntax trees at end of typer]] // <console> private[this] val I: Integer = scala.this.Predef.int2Integer($line3.$read.$iw.$iw.a); 
+4
source

Source: https://habr.com/ru/post/1202958/


All Articles