Welche Beziehungen bestehen zwischen Any, AnyVal, AnyRef, Object und wie werden sie bei Verwendung in Java-Code zugeordnet?

110

Normalerweise versuche ich jede Kombination, bis sie kompiliert ist. Kann jemand erklären, was ich wo verwenden soll?

huynhjl
quelle

Antworten:

124

Ich werde Chris ' Antwort in einer Hinsicht nicht zustimmen . Die Klassen Any, AnyRefund AnyVal sind Klassen. Sie werden jedoch aufgrund der inhärenten Einschränkungen der JVM nicht als Klassen im Bytecode angezeigt.

Dies ergibt sich aus der Tatsache, dass nicht alles in Java ein Objekt ist. Neben Objekten gibt es Grundelemente. Alle Objekte in Java stammen von ab java.lang.Object, aber Grundelemente sind getrennt und derzeit * für einen Programmierer nicht erweiterbar. Beachten Sie auch, dass Grundelemente "Operatoren" und keine Methoden haben.

In Scala, auf der anderen Seite, alles ist ein Objekt, gehören alle Objekte zu einer Klasse, und sie interact durch Methoden. Der generierte JVM-Bytecode spiegelt dies nicht wider, aber das macht sie nicht weniger, genauso wie Java Generika hat, obwohl der Bytecode sie nicht hat.

In Scala stammen also alle Objekte ab Any, und dazu gehört sowohl, was Java als Objekte betrachtet, als auch was Java als Grundelemente betrachtet. In Java gibt es kein Äquivalent, da es keine solche Vereinheitlichung gibt.

Alles, was in Java als primitiv betrachtet wird, stammt von AnyValScala ab. Bis Scala 2.10.0 AnyValversiegelt war und Programmierer es nicht erweitern konnten. Es sollte interessant sein zu sehen, was mit Scala in .Net passieren wird, da die Interoperabilität allein erfordert, dass Scala zumindest benutzerdefinierte "Grundelemente" erkennt.

Ebenfalls erweitert Anywird AnyRef, was äquivalent zu java.lang.Object(auf jeden Fall auf der JVM) ist.

Bis zu Scala 2.9.x konnte ein Benutzer sie nicht von Java aus erweitern Anyoder AnyValreferenzieren, aber es gab andere Verwendungszwecke, für die sie in Scala verwendet werden konnten. Geben Sie insbesondere Signaturen ein:

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

Was jedes bedeutet, sollte aus der Klassenhierarchie ersichtlich sein. Bemerkenswert ist jedoch, dass fund hwird automatisch boxen, wird aber gnicht. Das ist ein bisschen das Gegenteil von dem, was Java tut fund hwas nicht spezifiziert werden kann und g(definiert mit java.lang.Object) Auto-Boxing verursachen würde.

Ab Scala 2.10.0 kann der Benutzer jedoch erweitern AnyValoder Anymit der folgenden Semantik:

  • Wenn eine Klasse erweitert wird AnyVal, wird unter bestimmten Bedingungen keine Instanz für sie auf dem Heap erstellt. Dies bedeutet, dass die Felder dieser Klasse (in 2.10.0 ist nur ein einziges Feld zulässig - ob sich dies ändert, bleibt abzuwarten) auf dem Stapel verbleiben, unabhängig davon, ob es sich um Grundelemente oder Verweise auf andere Objekte handelt. Dies ermöglicht Erweiterungsmethoden ohne die Instanziierungskosten.

  • Wenn ein Merkmal erweitert wird Any, kann es sowohl für erweiterte AnyRefals auch für erweiterte Klassen verwendet werden AnyVal.

PS: Meiner Ansicht nach wird Java wahrscheinlich C # folgen, um "struct" -Primitive und möglicherweise typedefs zuzulassen, da sich Parallelität ohne Rückgriff auf sie mit guter Leistung als schwierig herausstellt.

Daniel C. Sobral
quelle
2
Ein Update: ab Scala 2.9.2 AnyValist definiert als sealed trait AnyVal extends Any. In Scala 2.10 hat sich dies jedoch geändert abstract class AnyVal extends Any with NotNull, und es ist jetzt möglich, es AnyValmit der neuen Funktion für Wertklassen zu erweitern , z class MyValue(val u: Int) extends AnyVal.
Ebruchez
@ebruchez Danke für den Hinweis. Ich habe meine Antwort mit einem Überblick über die neuen Funktionen aktualisiert.
Daniel C. Sobral
In welcher Beziehung stehen Nothing und Null dazu?
Gaurav Khare
41

Das gesehen? Der Text der Seite enthält einige Anmerkungen zur Java-Interoperabilität. http://www.scala-lang.org/node/128

Scala Class Heierarchy

Mitch Blevins
quelle
5

Anyund AnyValsind, glaube ich, Teil des Scala- Typ-Systems und keine Klassen als solche (genauso wie Nothingein Typ, keine Klasse). Sie können sie nicht explizit aus Java-Code heraus verwenden.

Bei der Java / Scala-Interoperation Objecterwartet eine Methode, die Java akzeptiert, jedoch eine Scala Any/ AnyRef.

Was versuchst du eigentlich zu tun?

oxbow_lakes
quelle
Ich versuche, dieses Thema besser zu verstehen, damit ich weiß, welchen Typ ich verwenden soll, wenn Java Scala aufrufen soll oder umgekehrt. Diese Antwort stackoverflow.com/questions/2334200/… und ihre Besetzung AnyReferinnerten mich nur daran, dass dies für mich immer noch mysteriös war.
Huynhjl