Quali sono le relazioni tra Any, AnyVal, AnyRef, Object e come vengono mappate quando vengono utilizzate nel codice Java?


111

Di solito finisco per provare ogni combinazione fino a quando non viene compilata. Qualcuno può spiegare cosa dovrei usare e dove?

Risposte:


125

Non sono d'accordo con la risposta di Chris sotto un aspetto. Le classi Any, AnyRefe AnyVal sono classi. Ma non appaiono come classi in bytecode, a causa delle limitazioni intrinseche della JVM.

Ciò deriva dal fatto che non tutto in Java è un oggetto. Oltre agli oggetti, ci sono primitive. Tutti gli oggetti in Java discendono da java.lang.Object, ma le primitive sono messe a parte e, attualmente * , non sono estensibili da un programmatore. Nota anche che le primitive hanno "operatori", non metodi.

In Scala, invece, tutto è un oggetto, tutti gli oggetti appartengono a una classe e interagiscono tramite metodi. Il bytecode JVM generato non riflette questo, ma questo non li rende meno, proprio come Java ha generics, anche se il bytecode non li ha.

Quindi, in Scala, tutti gli oggetti discendono da Any, e questo include sia ciò che Java considera oggetti sia ciò che Java considera primitive. Non esiste un equivalente in Java perché non esiste tale unificazione.

Tutto ciò che è considerato primitivo in Java discende da AnyValScala. Fino a Scala 2.10.0, è AnyValstato sigillato ei programmatori non erano in grado di estenderlo. Dovrebbe essere interessante vedere cosa accadrà con Scala su .Net, poiché la sola interoperabilità richiede che Scala riconosca almeno le "primitive" definite dall'utente.

Anche l'estensione Anyè AnyRef, che è equivalente a java.lang.Object(sulla JVM in ogni caso).

Fino a Scala 2.9.x, un utente non poteva estendere Anyo AnyVal, non li riferimento da Java, ma non vi erano altri usi potrebbero essere messi a in Scala. In particolare, le firme del tipo:

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

Ciò che ciascuno significa dovrebbe essere ovvio dalla gerarchia di classe. Da notare, tuttavia, è che fe hverrà auto-box, ma gnon lo farà. Che è un po il contrario di quello che fa Java, in quella fe hnon può essere specificato, e g(definito con java.lang.Object) causerebbe auto-boxing.

A partire da Scala 2.10.0, tuttavia, l'utente può estendere AnyValo Any, con la seguente semantica:

  • Se una classe si estende AnyVal, non verrà creata alcuna istanza sull'heap in determinate condizioni. Ciò significa che i campi di questa classe (nella 2.10.0 è consentito solo un singolo campo - resta da vedere se cambierà) rimarranno sullo stack, siano essi primitivi o riferimenti ad altri oggetti. Ciò consente metodi di estensione senza il costo di istanziazione.

  • Se un tratto si estende Any, può essere utilizzato sia con le classi che si estendono sia con le classi che si AnyRefestendono AnyVal.

PS: Dal mio punto di vista, è probabile che Java segua C # nel consentire primitive "struct" e forse typedef, poiché il parallelismo senza ricorrere ad essi si sta dimostrando difficile da realizzare con buone prestazioni.


2
Un aggiornamento: a partire da Scala 2.9.2, AnyValè definito come sealed trait AnyVal extends Any. Ma in Scala 2.10 questo è cambiato a abstract class AnyVal extends Any with NotNull, ed ora è possibile estendere AnyValcon la nuova funzione classi di valore, ad esempio: class MyValue(val u: Int) extends AnyVal.
ebruchez

@ebruchez Grazie per la nota. Ho aggiornato la mia risposta con una panoramica delle nuove funzionalità.
Daniel C. Sobral

Come si relaziona Nothing and Null a questo?
Gaurav Khare


5

Anye AnyValsono, credo, parte del sistema dei tipi scala e non sono classi in quanto tali (allo stesso modo che Nothingè un tipo, non una classe). Non è possibile utilizzarli esplicitamente dall'interno del codice Java.

Tuttavia, nell'interoperabilità Java / Scala, un metodo che accetta un Java Objectsi aspetterà un scala Any/ AnyRef.

Cosa stai effettivamente tentando di fare?


Sto cercando di capire meglio questo argomento in modo da sapere quale tipo dovrei usare quando ho intenzione di fare in modo che Java chiami Scala o viceversa. Questa risposta stackoverflow.com/questions/2334200/… e il suo cast AnyRefmi hanno ricordato che questo era ancora misterioso per me.
huynhjl
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.