Why does it become a Java class even if scala passes the type parameters to the scala class?

Asked 2 years ago, Updated 2 years ago, 93 views

Thank you for your help. I'm a beginner at scala. I'm worried because I don't know the reason for the following code behavior.

scala>case class MyVector [A]() {
  def test(init:A) = {
    println("type="+init.getClass)
  }
}
scala>(new MyVector [Int]( ).test(3)
type = class java.lang.Integer

I gave you Int, so I would like it to be Int instead of Integer...

Thank you for your cooperation.

java scala

2022-09-30 20:28

2 Answers

It depends on how JVM works.

As a general assumption, JVM cannot specify a primitive type as a type parameter. Therefore, in Java, if you specify int as the type parameter, Automatically replaces Integer, which is a non-primitive type corresponding to int, at compile time.

Scala using JVM cannot reverse this assumption. In the code illustrated by , A (=init.getClass) is Integer instead of Int.


2022-09-30 20:28

The Java specification requires that the type (collectively) used for the generics inherit the Object class.Therefore, a generic variable cannot have primitive data that does not inherit the Object class. In the case of Scala, it is determined at the time of compilation whether the generic type is Object or Primitive.

For the test() methods, the Scala compiler considers type A to be the generic type that inherits the object and generates byte codes that can be considered Java code, such as:

public void test (Object init)
{
    System.out.println(
        (new StringBuilder())
            .append("type=")
            .append(init.getClass())
            .toString());
}

Note the type of argument init in the test() method. Object type. Object type containers with primitive type int values will be an error. By the way,

  • int<=>java.lang.Integer
  • short<=>java.lang.Short
  • float<=>java.lang.Float
  • double<=>java.lang.Double

If the above type conversion is possible, the compiler will change the int type to Integer type. Incorporate meddling code that allows for mutual implicit translation.This time, the value of type int is automatically converted to type java.lang.Integer just before it is passed as an argument to the test() method.As a result, getClass() returns java.lang.Integer.

Supplement:

Scala's Int is often associated with primitive type (int in Java), but it is not.Scala's Int has been given special treatment by the compiler for optimization, making it difficult to handle.Scala's compiler tries to treat what is described in scala.Int as Java's int type as much as possible, but if it is unavoidable, it also adds a magic/insurance code to be used as Integer.

Compilers generally do a good job of hiding int and java.lang.Integer, but sometimes they are not perfect.For example, try compiling the following code similar to this example (Scala 2.9.3 and earlier only):

case class GenericsIntBug [A<:Int]() {
    def test(init:A) = {
          println("type="+init.getClass)
    }
}

This creates a method that compiles but always causes exceptions at runtime.If you look at the byte code, inside this method, you are trying to call a method getClass() that does not exist while handling data of the primitive type int. Java is an uncompileable code such as:

public void test(int init)
{
    System.out.println(
        (new StringBuilder())
            .append("type=")
            .append(init.getClass()) .toString());
}

It's interesting, so if you're interested, I recommend disassembly of the process using scala.Int.Int. (Details of supplementary examples are posted in This Gist)


2022-09-30 20:28

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.