Первое практическое отличие состоит в том, что ленивые значения и объекты являются ленивыми, тогда как значения стремятся.
Основное отличие между объектами и ленивыми значениями состоит в том, что объект с точки зрения языков считается "singleton, «который с точки зрения jvm обычно рассматривается как статический член.Определение объекта в данном примере не может быть переопределено, как продемонстрировали другие, по той же причине статические члены не могут быть переопределены: без привязки к экземпляру невозможно представить виртуальный поиск функции.
object Foo { object Bar extends A; }
похож на следующий код Java:
class Foo {
private static class Bar extends A{}
public static Bar Bar = new Bar;
}
Если в приведенном выше примере, если подкласс C расширяет Foo, он не сможет переопределить определение Bar.Статический экземпляр Bar в Java будет доступен как Foo.Bar.C.Bar не означает то же самое, что и (новый C) .Bar.Я мог бы быть немного здесь, на самом деле я не пробовал декомпилировать scala-код, это просто пример, чтобы проиллюстрировать общую концепцию объектов как статических членов.,В прошлый раз, когда я проверял, они были реализованы путем сохранения скрытого поля в классе, которое отслеживало, какие ленивые значения были инициализированы.Для сохранения этого поля требуется блокировка, которая может вызвать проблемы с производительностью.
Одним из основных практических различий между отложенным значением val и объектом является обработка ошибки:
Если у меня есть:
class Foo() { throw new Exception("blah!"); }
object Stuff { object Bar extends Foo { val x = "hi" } }
Stuff.Bar
//exception "blah!" thrown.
Stuff.Bar.x
//NoClassDefFoundError: Could not initialize Stuff$Bar$
тогда как если я это сделаю:
object Stuff2 { lazy val Bar = new Foo() { val x = "hi" } }
Stuff2.Bar
// "blah!"
Stuff2.Bar.x
// "blah!"
«NoClassDefFoundError» может быть действительно запутанным, и, поскольку это ошибка, а не исключение, он может нарушить код обработки ошибок, который (соответственно) перехватывает / регистрирует «Исключение», но позволяетошибки для распространения.Я мог бы даже рассмотреть такого рода ошибку в языке Scala, поскольку этот вариант использования фактически указывает на исключительное условие, а не на ошибку JVM.Я видел NoClassDefFoundErrors при доступе к объектам, которые зависели от внешних ресурсов (например, соединения с базой данных или файлы на диске).Только первый доступ регистрирует основную причину, поэтому для правильной отладки такой проблемы обычно требуется перезапуск сервера приложений.