En este código:
class Foo[T] {
def bar(i: T) = i
}
object Main {
def main(args: Array[String]) {
val f = new Foo[Int]
f.bar(5)
}
}
La invocación de bar
debería caja primero el número entero. Compilar con Scala y 2.8.1 usando:
javap -c -l -private -verbose -classpath <dir> Main$
para ver el código de bytes producido por el método main
de los rendimientos Main
clase:
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
...
Se puede ver la llamada a BoxesRunTime
antes de la llamada a bar
.
BoxesRunTime
es un objeto que contiene métodos de boxeo para tipos primitivos, por lo que debe haber exactamente una instancia en total. El truco aquí es que este archivo particular en la biblioteca fue escrito en Java, y las conversiones son métodos estáticos. Por esta razón, no hay instancias de él en tiempo de ejecución, aunque usarlo en el código de Scala se siente como si fuera un objeto.
Probablemente deberías buscar primitivos en caja (por ejemplo, java.lang.Integer) con JProfile, aunque no estoy seguro de cómo funciona la JVM y si realmente puede reescribir el código en tiempo de ejecución y optimizarlo para evitar el boxeo. Que yo sepa, no se debe aplicar la especialización (pero creo que CLR lo hace). Algunas microbenchmarks con y sin la situación del boxeo son otra forma de descubrir qué sucede en el tiempo de ejecución.
EDIT:
Lo anterior está asumiendo que un parámetro de tipo no fue anotado con la @specialized
anotación. En este caso, se puede evitar el boxeo/unboxing. Ciertas clases en la biblioteca estándar están especializadas. Ver this sid.
La especialización se produce para la función anonymous classes 'Test $$ anonfun $ #', ya que las funciones son especializadas. Sin embargo, estas clases anónimas de función se usan dentro de los métodos 'map' y' filter' que no están especializados y llaman a su 'genérico' apply' predeterminado, que espera un objeto - el boxeo debería ocurrir allí. Si descompilas el código de 'TraversableLike', y buscas' map' o 'filter', deberían tener invocaciones a' BoxesRunTime'. – axel22