В этом коде:
class Foo[T] {
def bar(i: T) = i
}
object Main {
def main(args: Array[String]) {
val f = new Foo[Int]
f.bar(5)
}
}
При вызове bar
сначала должно быть целое число.Компиляция с Scala 2.8.1 и использование:
javap -c -l -private -verbose -classpath <dir> Main$
для просмотра байт-кода, созданного для метода main
класса Main
, дает:
public void main(java.lang.String[]);
...
9: iconst_5
10: invokestatic #24; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
13: invokevirtual #28; //Method Foo.bar:(Ljava/lang/Object;)Ljava/lang/Object;
16: pop
17: return
...
Вы можете увидетьвызов BoxesRunTime
перед вызовом bar
.
BoxesRunTime
- это объект, который содержит методы бокса для примитивных типов, поэтому в общей сложности должен быть ровно один экземпляр.Хитрость в том, что этот конкретный файл в библиотеке был написан на Java, и преобразования являются статическими методами.По этой причине во время выполнения нет никаких экземпляров этого кода, хотя использование его в коде Scala выглядит так, как будто это объект.
Вы, вероятно, должны искать примитивы в штучной упаковке (например, java.lang.Integer) сJProfile, хотя я не уверен, как работает JVM и может ли он на самом деле переписать код во время выполнения и оптимизировать его, чтобы избежать упаковки.Насколько мне известно, это не должно применять специализацию (но я считаю, что CLR делает).Несколько микробенчмарков с ситуацией бокса и без нее - еще один способ выяснить, что происходит во время выполнения.
РЕДАКТИРОВАТЬ:
Выше предполагается, что параметр типа не был аннотирован с @specialized
аннотация.В этом случае бокс / распаковка можно избежать.Некоторые классы в стандартной библиотеке являются специализированными.Смотрите этот sid .