Обычно я пытаюсь использовать каждую комбинацию до ее компиляции. Может кто-нибудь объяснить, что я должен использовать где?
Каковы отношения между Any, AnyVal, AnyRef, Object и как они отображаются при использовании в Java-коде?
Ответ 1
Я не соглашусь с ответом Криса на один вопрос. Классы Any
, AnyRef
и AnyVal
являются классами. Но они не отображаются как классы в байт-коде, из-за внутренних ограничений JVM.
Это связано с тем, что не все в Java является объектом. В дополнение к объектам есть примитивы. Все объекты в Java являются потомками из java.lang.Object
, но примитивы разделены и, в настоящее время * не расширяются программистом. Также обратите внимание, что примитивы имеют "операторы", а не методы.
В Scala, с другой стороны, все является объектом, все объекты принадлежат классу, и они взаимодействуют с помощью методов. Созданный байт-код JVM не отражает этого, но это не делает их менее важными, так же как Java имеет дженерики, хотя байт-код не имеет их.
Итак, в Scala все объекты являются потомками из Any
, и это включает в себя как то, что Java рассматривает объекты, так и то, что Java считает примитивами. В Java нет эквивалента, потому что такой унификации нет.
Все, что считается примитивным в Java, является потомком от AnyVal
в Scala. До Scala 2.10.0, AnyVal
было запечатано, и программисты не смогли его продлить. Интересно посмотреть, что произойдет с Scala на .Net, так как только совместимость требует Scala, чтобы хотя бы распознать пользовательские "примитивы".
Также расширение Any
равно AnyRef
, что эквивалентно java.lang.Object
(на JVM во всяком случае).
До Scala 2.9.x пользователь не мог расширять Any
или AnyVal
, а также ссылаться на них с Java, но были и другие применения, которые они могли бы использовать в Scala. В частности, введите подписи:
def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)
То, что каждое средство должно быть очевидно из иерархии классов. Следует отметить, однако, что f
и h
будут автоматически установлены, но g
не будет. Это немного противоположно тому, что делает Java, поскольку f
и h
не могут быть указаны, а g
(определенный с помощью java.lang.Object
) приведет к автоматическому боксу.
Начиная с Scala 2.10.0, пользователь может расширить AnyVal
или Any
со следующей семантикой:
-
Если класс расширяет
AnyVal
, для определенных условий для кучи при определенных условиях для него не создается экземпляр. Это означает, что поля этого класса (на 2.10.0 допускается только одно поле - будет ли это изменено, пока не видно) останется в стеке, являются ли они примитивами или ссылками на другие объекты. Это позволяет использовать методы расширения без затрат на создание экземпляра. -
Если черта расширяет
Any
, то ее можно использовать с обоими классами, которые расширяютAnyRef
и классы, расширяющиеAnyVal
.
PS: По моему мнению, Java, вероятно, будет следовать за С#, позволяя примитивам "struct" и, возможно, typedefs, так как parallelism, не прибегая к ним, сложно выполнить с хорошей производительностью.
Ответ 2
Видели это? В тексте страницы есть некоторые замечания по совместимости Java. http://www.scala-lang.org/node/128
Ответ 3
Any
и AnyVal
являются, я считаю, частью системы scala и не являются классами как таковыми (так же, как Nothing
является типом, а не класс). Вы не можете использовать их явно из кода Java.
Тем не менее, при взаимодействии Java/ Scala метод, который принимает Java Object
, ожидает scala Any
/AnyRef
.
Что вы на самом деле пытаетесь сделать?