Quais são os relacionamentos entre Any, AnyVal, AnyRef, Object e como eles são mapeados quando usados ​​no código Java?

111

Eu geralmente acabo tentando todas as combinações até compilar. Alguém pode explicar o que devo usar onde?

Huynhjl
fonte

Respostas:

125

Eu discordo da resposta de Chris em um aspecto. As classes Any, AnyRefe AnyVal são classes. Mas eles não aparecem como classes no bytecode, devido às limitações intrínsecas da JVM.

Isso decorre do fato de que nem tudo em Java é um objeto. Além de objetos, existem primitivos. Todos os objetos em Java são descendentes de java.lang.Object, mas os primitivos são separados e, atualmente * , não extensíveis por um programador. Observe também que os primitivos têm "operadores", não métodos.

No Scala, por outro lado, tudo é um objeto, todos os objetos pertencem a uma classe e interagem por meio de métodos. O bytecode da JVM gerado não reflete isso, mas isso não os torna menos, assim como o Java tem genéricos, embora o bytecode não os tenha.

Então, em Scala, todos os objetos são descendentes de Any , e isso inclui o que Java considera objetos e o que Java considera primitivos. Não há equivalente em Java porque não existe tal unificação.

Tudo o que é considerado primitivo em Java é descendente de AnyValScala. Até o Scala 2.10.0, ele AnyValera selado e os programadores não podiam estendê-lo. Deve ser interessante ver o que acontecerá com Scala em .Net, uma vez que a interoperabilidade por si só exige que o Scala reconheça pelo menos "primitivas" definidas pelo usuário.

Também Anyé estendido AnyRef, que é equivalente a java.lang.Object(na JVM de qualquer maneira).

Até Scala 2.9.x, um usuário não poderia estender Anyou AnyVal, nem fazer referência a eles a partir de Java, mas não foram para outros usos que poderiam ser colocados no Scala. Especificamente, digite assinaturas:

def f(x: AnyVal) = println(x)
def g(x: AnyRef) = println(x)
def h(x: Any) = println(x)

O que cada um significa deve ser óbvio na hierarquia de classes. Digno de nota, no entanto, é que fe hirá encaixotar automaticamente, mas gnão irá. Isso é um pouco o oposto do que Java faz, pois fe hnão pode ser especificado, e g(definido com java.lang.Object) causaria caixa automática.

No entanto, a partir do Scala 2.10.0, o usuário pode estender AnyValou Any, com a seguinte semântica:

  • Se uma classe estender AnyVal, nenhuma instância será criada para ela no heap sob certas condições. Isso significa que os campos desta classe (no 2.10.0 apenas um único campo é permitido - se isso vai mudar, resta ver) ficarão na pilha, sejam eles primitivos ou referências a outros objetos. Isso permite métodos de extensão sem o custo de instanciação.

  • Se uma característica se estende Any, ela pode ser usada com as classes que se estendem AnyRefe com as que se estendem AnyVal.

PS: Na minha opinião, Java provavelmente seguirá o C # ao permitir primitivas "struct" e talvez typedefs, pois o paralelismo sem recorrer a eles está se mostrando difícil de realizar com bom desempenho.

Daniel C. Sobral
fonte
2
Uma atualização: a partir de Scala 2.9.2, AnyValé definido como sealed trait AnyVal extends Any. Mas no Scala 2.10 isso mudou para abstract class AnyVal extends Any with NotNull, e agora é possível estender AnyValcom o novo recurso de classes de valor, por exemplo:class MyValue(val u: Int) extends AnyVal .
ebruchez
@ebruchez Obrigado pela nota. Atualizei minha resposta com uma visão geral dos novos recursos.
Daniel C. Sobral,
Como Nothing and Null se relaciona com isso?
Gaurav Khare
41

Visto isso? O texto da página contém alguns comentários sobre interoperabilidade de java. http://www.scala-lang.org/node/128

Scala Class Heierarchy

Mitch Blevins
fonte
5

Anye AnyValsão, creio eu, parte do sistema de tipo scala e não são classes como tais (da mesma forma queNothing é um tipo, não uma classe). Você não pode usá-los explicitamente de dentro do código Java.

No entanto, na interoperação Java / Scala, um método que aceita um Java Objectespera um scala Any/ AnyRef.

O que você está realmente tentando fazer?

oxbow_lakes
fonte
Estou tentando entender este tópico melhor para saber que tipo devo usar quando estou planejando fazer o Java chamar Scala ou vice-versa. Esta resposta stackoverflow.com/questions/2334200/… e seu elenco AnyRefapenas me lembrou que isso ainda era misterioso para mim.
Huynhjl