Есть ли причина, по которой ленивая инициализация не может быть встроена в Java?

10

Поскольку я работаю на сервере с абсолютно отсутствующим непостоянным состоянием для пользователей, каждый объект, связанный с пользователем, развертывается при каждом запросе.

Следовательно, я часто выполняю ленивую инициализацию свойств объектов, которые могут остаться неиспользованными.

protected EventDispatcher dispatcher = new EventDispatcher();

Становится ...

protected EventDispatcher<EventMessage> dispatcher;

public EventDispatcher<EventMessage> getEventDispatcher() {
    if (dispatcher == null) {
        dispatcher = new EventDispatcher<EventMessage>();
    }
    return dispatcher;
}

Есть ли какая-то причина, по которой это не может быть встроено в Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


Как упомянуто ниже в комментариях, я понимаю, что язык может теоретически развиваться и включать в себя практически все, что вы захотите. Я ищу практическое измерение возможности. Будет ли это противоречить другим функциям? Является ли реализация достаточно простой, чтобы хорошо работать с JVM, как она существует? И даже, это хорошая идея?

Николь
источник
2
не знаю, но пример кода не является потокобезопасным
Armand
2
@ Алисон synchronizedключевое слово будет работать так же, как если бы оно было в методе. Я предполагаю, что было бы какое-то приспособление более сложных методов строительства. В моем конкретном случае использования, из-за характера проблемы, для каждого запроса, как своего собственного мира, синхронизация бессмысленна.
Николь
В C # Lazy есть в библиотеке, но поддерживается языком. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Есть ли в Java лямбды, делегаты и замыкания? Кстати, вы хотите спросить об этом на SO, так что Jon Skeet & Co. может поделиться своей мудростью.
Работа
3
Вы можете построить практически все на любом языке. Но бюджет сложности и список возможностей ограничены, и разработчики языка могут включать только то, что они считают наиболее важным (ну, кроме Ларри Уолла - особенно в Perl 6, также называемом «Все ваши парадигмы принадлежат нам»).
1
Основная проблема заключается в том, что Java является единственным статически типизированным языком без возможности метапрограммирования. В Си вы можете написать это как макрос за десять минут. В C ++ вы можете написать это как шаблон за две минуты. В Java вы можете ... вставлять и изменять.
Кевин Клайн

Ответы:

14

Вот восьмистраничный ответ на ваш вопрос: http://tinlizzie.org/~awarth/papers/fool07.pdf

Если я могу попытаться грубо суммировать проблемы с добавлением лени, это угловые случаи. Есть много предостережений по поводу побочных эффектов. Рассмотрим, в вашем примере, если у конструктора были видимые побочные эффекты, такие как столкновение с глобальным счетчиком или ввод-вывод ... Трудно представить, когда это произойдет. Или рассмотрите еще более неприятные побочные эффекты в отношении исключений (они выбрасываются ... когда вы ссылаетесь на ленивый объект?)

Просто перейдите к разделу 6 в приведенном выше документе. (И восхищайтесь всей формальной логикой системы типов на страницах, которые вы пропускаете ...)

PT
источник
Принятие этого ответа из-за глубины, в которой документ рассматривает эту функцию. Спасибо!
Николь
TL; DR, когда вы программируете, вы должны знать, что происходит, чтобы предотвратить побочные эффекты, с ленивостью, это действительно может выйти из-под контроля. Если вы знаете Hibernate и какие проблемы возникают у некоторых людей, просто вообразите то же самое для всего языка.
Вальфрат
10

Конечно, это в высшей степени возможно. На самом деле, Scala уже имеет именно эту функцию! (Scala является языком JVM и компилируется в байт-код). Вот часть источника scala:

class Foo {
  lazy val bar = "Hello World"
}

А вот как выглядит промежуточная форма скомпилированного кода:

scalac -Xprint:icode Foo.scala

[[syntax trees at end of icode]]// Scala source: Foo.scala
package <empty> {
  class Foo extends java.lang.Object with ScalaObject {
    @volatile protected var bitmap$0: Int = 0;
    lazy private[this] var bar: java.lang.String = _;
    <stable> <accessor> lazy def bar(): java.lang.String = {
      if (Foo.this.bitmap$0.&(1).==(0))
        {
          Foo.this.synchronized({
            if (Foo.this.bitmap$0.&(1).==(0))
              {
                Foo.this.bar = "Hello World";
                Foo.this.bitmap$0 = Foo.this.bitmap$0.|(1);
                ()
              };
            scala.runtime.BoxedUnit.UNIT
          });
          ()
        };
      Foo.this.bar
    };
    def this(): Foo = {
      Foo.super.this();
      ()
    }
  }

}

oxbow_lakes
источник
Так как же это согласуется с ответом PT по адресу programmers.stackexchange.com/a/110958/24257 ?
Pacerier
6

Я думаю, что сначала вам нужно добавить реальные свойства в язык Java, а не полагаться на идиому getX / setX. Таким образом, вы можете просто пометить свойство как ленивое (и синхронизированное, только для чтения и т. Д.).

Сортировка чего просят здесь (Objective-C, но понятие относится).

Мартин Викман
источник
0

Конечно, это может быть добавлено в Java, ключевое слово lazy может быть реализовано как синтаксический сахар. Однако, будет ли это реализовано, зависит от видения разработчиков компиляторов.

Мичиэль Оверим
источник