Я почти уверен, что это как-то связано с упаковкой / распаковкой примитивов. Если вы пишете универсальный код для работы с примитивами, вы должны поместить примитив в коробку, а затем распаковать его в том месте, где вы использовали его в качестве примитива. Я не уверен, какой алгоритм распаковки используется, но я предполагаю, что он имеет следующие черты:
if(box == null)
default value
else
box.unbox
Следовательно, очень странно, я мог бы добавить, что значение по умолчанию для поля t
в вашем классе простой оболочки всегда будет null
, так как поле всегда будет в штучной упаковке примитивный, так как генерики реализованы на уровне JVM по типу стирания. Поэтому все, что видит JVM, это то, что t
имеет тип Object
со значением null
. Поэтому метод get
всегда будет возвращать null
, но когда универсальный метод get
должен возвращать примитивный тип, null
распаковывается со значением по умолчанию.
Кроме того, немного возни с отражением действительно показывает, что поле действительно null
.
val sw = new SimpleWrap[Boolean]
sw.getClass.getDeclaredFields.map {
f => f.setAccessible(true)
f.get(sw)
}
О, удовольствие null
с. Одним из решений этой проблемы было бы использование аннотации 2.8 @specialised
, если это было реализовано в используемой вами ночной сборке.
Или, что еще лучше, компилятор Scala может использовать в этих полях значения по умолчанию для коробок по умолчанию с действительными значениями по умолчанию используемых примитивов. Например, в случае SimpleWrap[Boolean]
, t
будет иметь тип Object
и значение java.lang.Boolean(false)
во время выполнения.
РЕДАКТИРОВАТЬ: Отчет об ошибке отправлено .
Еще одна странная вещь:
val x: Int = null.asInstanceOf[Int] // 0
val y: Boolean = null.asInstanceOf[Boolean] // false
Это то, что нужно решить, чтобы дженерики действительно были родовыми и имели согласованное поведение! На данный момент ваш метод get
не имеет согласованного поведения.
- Flaviu Cipcigan