Ссылочное равенство для java.lang.String в Scala

Можно было бы ожидать, что хотя строки неизменяемы, равенство значений и равенство ссылок не будут одинаковыми для объектов java.lang.String в Scala. Это означает, что два val, содержащих строки, не должны быть равны по ссылке, даже если их строки идентичны. Но вот что я получаю в 2.9.1.final REPL:

scala> val s1 = "a"; val s2 = "a"
s1: java.lang.String = a
s2: java.lang.String = a

scala> s1 eq s2
res0: Boolean = true

Любая идея, почему результат не был false? Тот же эксперимент с List("a") вместо "a" работает как положено. Метод eq отмечен как окончательный в AnyRef. Есть ли какая-то магия компилятора, сделанная специально для String или java.lang.String?


person Oleg Mirzov    schedule 09.04.2012    source источник


Ответы (2)


Да, это магия компилятора. В частности, это называется стажировка. Java также делает это, и это просто из соображений эффективности, таких как использование памяти и возможность сравнения без сравнения каждого символа. Вот статья об этом в Википедии. Вы также можете интернировать строки вручную с помощью метода intern().

person Luigi Plinge    schedule 09.04.2012

Из спецификации языка Java< /а>:

Строковый литерал — это ссылка на экземпляр класса String (§4.3.1, §4.3.3).

Более того, строковый литерал всегда ссылается на один и тот же экземпляр класса String. Это связано с тем, что строковые литералы — или, в более общем случае, строки, являющиеся значениями константных выражений (§15.28), — интернируются для совместного использования уникальных экземпляров с использованием метода String.intern.

person fredoverflow    schedule 09.04.2012
comment
Спасибо! Интересно, что когда я изменяю свой пример, чтобы начать с val s1 = "aa"; val s2 = "a" + "a", результат остается тем же, даже несмотря на то, что "a" + "a" не является константным выражением (не так ли?). Итак, похоже, что Scala делает немного больше, чем указано в спецификации Java. - person Oleg Mirzov; 09.04.2012
comment
Спецификация Java для константных выражений не похожа на Scala. Например, используя один из примеров, приведенных на этой странице константных выражений, "The integer " + java.lang.Long.MAX_VALUE + " is mighty big." не интернируется scalac. - person Luigi Plinge; 09.04.2012