Які взаємозв'язки між Any, AnyVal, AnyRef, Object і як вони відображаються при використанні в коді Java?


111

Я, як правило, пробую кожну комбінацію, поки вона не складеться. Хтось може пояснити, що я повинен використовувати де?

Відповіді:


125

Я НЕ згоден з Кріса відповідь в одному відношенні. Класи Any, AnyRefі AnyVal це заняття. Але вони не відображаються як класи в байт-коді через внутрішні обмеження JVM.

Це виникає через те, що не все на Java - це об’єкт. Крім предметів, існують примітиви. Усі об’єкти на Java походять від java.lang.Object, але примітиви встановлені один від одного і, на даний час * , не розширюються програмістом. Зауважте також, що у примітивів є "оператори", а не методи.

У Scala, з іншого боку, все є об'єктом, всі об'єкти належать до класу, і вони взаємодіють за допомогою методів. Згенерований байт-код JVM не відображає цього, але це не робить їх менш таким же, як у Java є дженерики, навіть якщо байт-код не має їх.

Так, у Scala всі об'єкти є нащадками Any, і це включає як те, що Java вважає об'єктами, так і те, що Java вважає примітивами. У Java немає еквівалента, оскільки такого об'єднання немає.

Все, що на Яві вважається примітивним, є нащадком від AnyValScala. Поки Scala 2.10.0 не AnyValбула запечатана, і програмісти не змогли її продовжити. Це має бути цікаво подивитися, що буде з Scala в .Net, оскільки одна з сумісних операцій закликає Scala хоча б визнати визначені користувачем "примітиви".

Також розширення Anyє AnyRef, що еквівалентно java.lang.Object(на СП у будь-якому випадку).

До 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, ймовірно, слідкує за C #, дозволяючи "структурувати" примітиви, а може бути і typedefs, оскільки паралелізм, не вдаючись до них, виявляється складно виконати з хорошими показниками.


2
Оновлення: станом на Scala 2.9.2 AnyValвизначається як sealed trait AnyVal extends Any. Але в Scala 2.10 це змінилося з abstract class AnyVal extends Any with NotNull, і тепер можна розширити AnyValза допомогою нової функції класів значень, наприклад: class MyValue(val u: Int) extends AnyVal.
ebruchez

@ebruchez Дякую за замітку. Я оновив свою відповідь оглядом нових можливостей.
Даніель К. Собрал

Як Ніщо і Ніщо ставиться до цього?
Гаурав Харе


5

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

Однак у взаємодії Java / Scala метод, який приймає Java Object, очікує масштабування Any/ AnyRef.

Що ви насправді намагаєтесь зробити?


Я намагаюся краще зрозуміти цю тему, щоб я знав, який тип я повинен використовувати, коли я планую на виклик Java Scala або навпаки. Ця відповідь stackoverflow.com/questions/2334200/… та її склад AnyRefпросто нагадували мені, що це все ще для мене таємниче.
huynhjl
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.