Каковы отношения между 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

Scala Class Heierarchy

Ответ 3

Any и AnyVal являются, я считаю, частью системы scala и не являются классами как таковыми (так же, как Nothing является типом, а не класс). Вы не можете использовать их явно из кода Java.

Тем не менее, при взаимодействии Java/ Scala метод, который принимает Java Object, ожидает scala Any/AnyRef.

Что вы на самом деле пытаетесь сделать?