Quelles sont les relations entre Any, AnyVal, AnyRef, Object et comment se mappent-elles lorsqu'elles sont utilisées dans le code Java?

111

Je finis généralement par essayer chaque combinaison jusqu'à ce qu'elle se compile. Quelqu'un peut-il expliquer ce que je dois utiliser où?

huynhjl
la source

Réponses:

125

Je ne suis pas d'accord avec la réponse de Chris sur un point. Les classes Any, AnyRefet AnyVal sont des classes. Mais elles n'apparaissent pas comme des classes en bytecode, en raison des limitations intrinsèques de la JVM.

Cela vient du fait que tout en Java n'est pas un objet. En plus des objets, il existe des primitives. Tous les objets en Java sont des descendants de java.lang.Object, mais les primitives sont mises à part et, actuellement * , non extensibles par un programmeur. Notez également que les primitives ont des "opérateurs", pas des méthodes.

Dans Scala, par contre, tout est un objet, tous les objets appartiennent à une classe et ils interagissent via des méthodes. Le bytecode JVM généré ne reflète pas cela, mais cela ne les rend pas moins, tout comme Java a des génériques, même si le bytecode ne les a pas.

Ainsi, dans Scala, tous les objets sont des descendants de Any, et cela inclut à la fois ce que Java considère comme des objets et ce que Java considère comme des primitives. Il n'y a pas d'équivalent en Java car une telle unification n'existe pas.

Tout ce qui est considéré comme primitif en Java est un descendant de AnyValScala. Jusqu'à ce que Scala 2.10.0 AnyValsoit scellé et les programmeurs ne pouvaient pas l'étendre. Il devrait être intéressant de voir ce qui va se passer avec Scala sur .Net, puisque la seule interopérabilité appelle Scala à au moins reconnaître les "primitives" définies par l'utilisateur.

L'extension Anyest également AnyRef, ce qui équivaut à java.lang.Object(sur la JVM en tout cas).

Jusqu'à Scala 2.9.x, un utilisateur ne pouvait pas les étendre Anyou AnyVal, ni les référencer à partir de Java, mais il y avait d' autres utilisations auxquelles ils pouvaient être utilisés dans Scala. Plus précisément, tapez les signatures:

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

Ce que chacun signifie devrait être évident à partir de la hiérarchie des classes. Il convient de noter, cependant, est que fet la hvolonté boîte automatique, mais gne sera pas. C'est un peu le contraire de ce que fait Java, en cela fet hne peut pas être spécifié, et g(défini avec java.lang.Object) provoquerait un auto-boxing.

À partir de Scala 2.10.0, cependant, l'utilisateur peut étendre AnyValou Any, avec la sémantique suivante:

  • Si une classe s'étend AnyVal, aucune instance ne sera créée pour elle sur le tas sous certaines conditions. Cela signifie que les champs de cette classe (sur 2.10.0, un seul champ est autorisé - il reste à voir si cela changera) resteront sur la pile, qu'il s'agisse de primitives ou de références à d'autres objets. Cela permet des méthodes d'extension sans le coût d'instanciation.

  • Si un trait s'étend Any, il peut être utilisé avec les classes qui s'étendent AnyRefet les classes qui s'étendent AnyVal.

PS: De mon point de vue, Java est susceptible de suivre C # en autorisant les primitives «struct», et peut-être les typedefs, car le parallélisme sans y recourir s'avère difficile à réaliser avec de bonnes performances.

Daniel C. Sobral
la source
2
Une mise à jour: à partir de Scala 2.9.2, AnyValest définie comme sealed trait AnyVal extends Any. Mais dans Scala 2.10 cela a changé pour abstract class AnyVal extends Any with NotNull, et il est maintenant possible d'étendre AnyValavec les nouvelles classes de valeur caractéristique, par exemple: class MyValue(val u: Int) extends AnyVal.
ebruchez
@ebruchez Merci pour la note. J'ai mis à jour ma réponse avec un aperçu des nouvelles fonctionnalités.
Daniel C. Sobral
Quel est le lien entre Nothing and Null et cela?
Gaurav Khare
5

Anyet AnyValfont, je crois, partie du système de types scala et ne sont pas des classes en tant que telles (de la même manière qu'un Nothingtype, pas une classe). Vous ne pouvez pas les utiliser explicitement à partir du code Java.

Cependant, dans l'interopérabilité Java / Scala, une méthode qui accepte un Java Objectattendra un scala Any/ AnyRef.

Qu'essayez-vous réellement de faire?

oxbow_lakes
la source
J'essaie de mieux comprendre ce sujet afin de savoir quel type je devrais utiliser lorsque je prévois que Java appelle Scala ou vice versa. Cette réponse stackoverflow.com/questions/2334200/… et son casting AnyRefme rappelaient que c'était encore mystérieux pour moi.
huynhjl le