Чи є якась причина лінивої ініціалізації не вбудована в 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
dunno, але приклад код не є безпечним для потоків
Armand

2
@Alison synchronizedключове слово працюватиме так само, як якщо б воно було за методом. Я гадаю, було б розміщення складніших методів будівництва. У моєму конкретному випадку використання, в силу природи проблеми, при кожному запиті як власному світі синхронізуватись безглуздо.
Ніколь

У C # Ледачий знаходиться в бібліотеці, але він підтримується мовою. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Чи є у Java лямбди, делегати та закриття? До речі, ви хочете запитати це так, щоб Jon Skeet & co. можуть поділитися своєю мудрістю.
Робота

3
Ви можете створити майже все на будь-якій мові. Але бюджет складності та перелік можливостей обмежені, і мовні дизайнери можуть включати лише те, що вони вважають найважливішим (ну, крім Ларрі Уолл - особливо в Perl 6 aka "Всі ваші парадигми належать нам").

1
Принципова проблема полягає в тому, що Java - це єдина статично типізована мова без метапрограмування. На C ви можете написати це як макрос за десять хвилин. В C ++ ви можете написати це як шаблон приблизно за дві хвилини. На Java ви можете ... вставляти та змінювати.
кевін клайн

Відповіді:


14

Ось восьмисторінкова відповідь на ваше запитання: http://tinlizzie.org/~awarth/papers/fool07.pdf

Якщо я можу спробувати і грубо узагальнити проблеми із додаванням лінощів, це наріжні випадки. Є багато застережень навколо побічних ефектів. Подумайте, у вашому прикладі, якби конструктор мав видимі побічні ефекти, такі як нахил глобального лічильника чи виконання вводу-виводу ... Важко міркувати про те, коли це станеться. Або врахуйте ще більш потворні побічні ефекти щодо винятків (вони кидаються ... коли ви посилаєтесь на ледачий об’єкт?)

Просто перейдіть до розділу 6 вищевказаної статті. (І захоплюйтеся всією формальною логікою системи типу на пропущених сторінках ...)


Прийняття цієї відповіді через глибину, в якій документ стосується цієї функції. Дякую!
Ніколь

TL; DR, коли ви програмуєте, ви повинні знати, що відбувається для запобігання побічних ефектів, а лінь - це справді може отримати руку. Якщо ви знаєте, що перебуває в сплячому режимі, і скільки проблем з цим мають деякі люди, просто уявіть собі те саме для всієї мови.
Вальфрат

10

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

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();
      ()
    }
  }

}


То як би це узгодити з відповіддю ПТ на programmers.stackexchange.com/a/110958/24257 ?
Pacerier

6

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

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


0

Звичайно, це можна додати до Java, ключове слово lazy може бути реалізовано як синтаксичний цукор. Однак, чим вона буде реалізована, залежить від бачення розробників-компіляторів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.