Відповіді:
Я НЕ згоден з Кріса відповідь в одному відношенні. Класи Any
, AnyRef
і AnyVal
це заняття. Але вони не відображаються як класи в байт-коді через внутрішні обмеження JVM.
Це виникає через те, що не все на Java - це об’єкт. Крім предметів, існують примітиви. Усі об’єкти на Java походять від java.lang.Object
, але примітиви встановлені один від одного і, на даний час * , не розширюються програмістом. Зауважте також, що у примітивів є "оператори", а не методи.
У Scala, з іншого боку, все є об'єктом, всі об'єкти належать до класу, і вони взаємодіють за допомогою методів. Згенерований байт-код JVM не відображає цього, але це не робить їх менш таким же, як у Java є дженерики, навіть якщо байт-код не має їх.
Так, у Scala всі об'єкти є нащадками Any
, і це включає як те, що Java вважає об'єктами, так і те, що Java вважає примітивами. У Java немає еквівалента, оскільки такого об'єднання немає.
Все, що на Яві вважається примітивним, є нащадком від AnyVal
Scala. Поки 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, оскільки паралелізм, не вдаючись до них, виявляється складно виконати з хорошими показниками.
Побачили це? Текст сторінки має деякі зауваження щодо сумісності Java. http://www.scala-lang.org/node/128
Any
і AnyVal
, я вважаю, є частиною системи типу scala і не є класами як такими (так само, Nothing
як тип, а не клас). Ви не можете використовувати їх явно з коду Java.
Однак у взаємодії Java / Scala метод, який приймає Java Object
, очікує масштабування Any
/ AnyRef
.
Що ви насправді намагаєтесь зробити?
AnyRef
просто нагадували мені, що це все ще для мене таємниче.
AnyVal
визначається якsealed trait AnyVal extends Any
. Але в Scala 2.10 це змінилося зabstract class AnyVal extends Any with NotNull
, і тепер можна розширитиAnyVal
за допомогою нової функції класів значень, наприклад:class MyValue(val u: Int) extends AnyVal
.