Почему Scala иногда прибегает к Java-объектам?

Я почти уверен, что этот вопрос задавался раньше, но мне не хватает слов, чтобы найти его.

scala> Seq[Any]( 3, 3.4 )
res0: Seq[Any] = List(3, 3.4)

scala> res0( 1 ).getClass
res1: Class[_] = class java.lang.Double

scala> Seq( 3, 3.4 )
res2: Seq[Double] = List(3.0, 3.4)

scala> res2( 1 ).getClass
res3: Class[Double] = double

Почему Скала обрабатывает мой Double ввод как java.lang.Double в пределах Seq[Any] но держит это как scala.Double при работе с Seq[AnyRef]? Есть ли способ предотвратить такое поведение и вместо этого всегда использовать типы Scala?

2 ответа

Решение

В Scala Double соответствует Java double но может получить автоматическую коробку и распакованы при необходимости, и это становится java.lang.Double когда он будет автоматически упакован. На практике для коллекций требуется автобокс примитивных переменных.

Типы коллекций, которые вы объявляете, выводятся на основании назначенного им значения, если тип не объявлен явно. Разница между двумя декларациями в вопросе заключается в том, что для Seq(value1,value2,...) вывод типа пытается найти "лучший" тип, придумывает Seq[Double] а потом интересует value1, value2 и так далее на основе этого типа (Scala Double). Если вы объявите тип явно как Seq[Any], вывод типа не выполняется (так как вы сами дали тип), и поэтому значения value1, value2 и т. д. не "вынуждены" интерпретироваться как имеющие фиксированный тип.

поскольку Seq является коллекцией, примитивы не допускаются и должны быть автоматически упакованы, поэтому Java double не может вписаться в то время как java.lang.Double Можно. Логика, которая пытается скрыть бокс и распаковку для Seq[Double] и прозрачно меняет примитив, и объект не входит в игру. На самом деле, в Seq[Any]каждый элемент может быть другого типа, что означает, что такой бокс и распаковка не могут работать в общем случае (в вашем примере, res0(0).getClass является Integer в отличие от res2(0).getClass который является двойным).

Таким образом, по сути, если вы не объявляете тип явно, вывод типа включается и сначала пытается найти общий тип для всех элементов коллекции, а затем преобразует все элементы в этот тип, в то время как параметр типа коллекции указан явно, ничего подобного не происходит, и все типы значений интерпретируются как "необработанные".

То, что происходит, это бокс. Потому что первый Seq[Any]Любые примитивы в нем будут возвращаться в коробочном виде. Во втором случае, потому что тип Seq[Double], доступ к участникам будет автоматически распакован (но все равно будет сохранен в Seq).

Попытка получить класс времени выполнения для примитивов неизбежно вызовет всевозможные проблемы. Попробуйте не нужно использовать getClass,

Другие вопросы по тегам