@ special не имеет отношения к стиранию типов, по крайней мере, в этом случае. Это означает, что дополнительная версия вашего класса генерируется с собственным типом в позиции. Это существенно экономит на упаковке / распаковке.
Итак, вы определяете класс как:
class MyClass[@specialized(Int) T] {
def foobar(t: T) = {}
}
и в результате вы получите два класса (приблизительно):
class Foobar[java.lang.Object] {
def foobar(t: java.lang.Object) = {}
}
class Foobar[int] {
def foobar(t: int) = {}
}
Вам необходимо иметь две реализации класса, потому что вы не всегда можете гарантировать, что будет вызвана та, которая имеет правильный нативный тип. Компилятор scala будет выбирать, какой из них вызывать. Обратите внимание, что java-компилятор не знает, что эта специализация имеет место, поэтому должен вызывать неспециализированные методы.
Фактически, вывод следующий (через JAD):
public class MyClass implements ScalaObject {
public void foobar(Object obj) { }
public void foobar$mcI$sp(int t) {
foobar(BoxesRunTime.boxToInteger(t));
}
public MyClass() { }
}
public class MyClass$mcI$sp extends MyClass {
public void foobar(int t) {
foobar$mcI$sp(t);
}
public void foobar$mcI$sp(int i) { }
public volatile void foobar(Object t) {
foobar(BoxesRunTime.unboxToInt(t));
}
public MyClass$mcI$sp() {}
}
Так что ваша проблема стирания типа не будет решена с помощью @ special.