Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala List[Int] becomes List<Object> in Java

Tags:

java

scala

I have the following list defined within a Scala object:

object Foo {
    val bar = List(1, 2, 3)
}

Which seems to become a scala.collection.immutable.List<Object> when I try to use it from Java. As a consequence, I have to use getters like Foo.bar().apply$mcII$sp(i) or apply with a cast to Integer/int.

Why is the generic type Object and not Integer? This also seems to be only the case for types that exist as Java primitives; List[MyType] becomes List<MyType> in Scala.

like image 614
beatngu13 Avatar asked Nov 21 '18 12:11

beatngu13


People also ask

How do I create a list object in Scala?

Uniform List can be created in Scala using List. fill() method. List. fill() method creates a list and fills it with zero or more copies of an element.

How do you define a list in Scala?

Syntax for defining a Scala List. val variable_name: List[type] = List(item1, item2, item3) or val variable_name = List(item1, item2, item3) A list in Scala is mostly like a Scala array. However, the Scala List is immutable and represents a linked list data structure.

How do I assign a list in Scala?

To append value inside the list object we have two approach shown below: val variable_name = List(value1, value2, value3 , soon..) 2. To assign value for ListBuffer we use += operator to assign its value anytime because ListBuffer is mutable in nature.

How do I start a list in Scala?

Scala lists are immutable by default. You cannot "add" an element, but you can form a new list by appending the new element in front. Since it is a new list, you need to reassign the reference (so you can't use a val). NB: In scala don't use the type Object but Any , AnyRef or AnyVal .


2 Answers

I have experienced a somewhat similar issue with Swagger not responding well to Scala.

I don't know why, but this bug/feature is related to Java's primitives that dont't have setters and getters (like objects). Since the Java compiler can't find a suiting object, it just compiles it down to Object.

Scala collections have made converters to fix this: https://docs.scala-lang.org/overviews/collections/conversions-between-java-and-scala-collections.html

The only workaround I can think about is to use: Foo.bar.toJava

Sources: Deserializing Scala list with Jackson

https://stackoverflow.com/a/52581955/2291510

Spring RequestParam formatter for Scala.Option

Good luck!

like image 121
Mr.Turtle Avatar answered Sep 24 '22 00:09

Mr.Turtle


This happens due to the fact that Java does not support primitive types in generic types, generics are a compile time construct only in Java, they do not exist in JVM bytecode, thus they must be convertible to Java's Object type, which primitives cannot.

If we compile the code using the -Xprint:jvm flag, you can see that List[Int] actually compiles to the non generic List:

package com.yuvalitzchakov.github {
  object Foo extends Object {
    private[this] val bar: List = _;
    <stable> <accessor> def bar(): List = Foo.this.bar;
    def <init>(): com.yuvalitzchakov.github.Foo.type = {
      Foo.super.<init>();
      Foo.this.bar = scala.collection.immutable.List.apply(scala.Predef.wrapIntArray(Array[Int]{1, 2, 3}));
      ()
    }
  }
}

If Foo.bar was a List[Integer], this would yield a List<Integer> in Java, instead of List<Object>

like image 45
Yuval Itzchakov Avatar answered Sep 20 '22 00:09

Yuval Itzchakov