C'è qualche ragione per cui un'inizializzazione pigra non può essere costruita in Java?

10

Dato che sto lavorando su un server che non ha assolutamente nessuno stato persistente per gli utenti, ogni oggetto relativo all'utente che abbiamo viene distribuito su ogni richiesta.

Di conseguenza spesso mi trovo a fare un'inizializzazione pigra delle proprietà degli oggetti che potrebbero non essere utilizzate.

protected EventDispatcher dispatcher = new EventDispatcher();

Diventa ...

protected EventDispatcher<EventMessage> dispatcher;

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

C'è qualche ragione per cui questo non possa essere integrato in Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();

Come accennato nei commenti, mi rendo conto che un linguaggio potrebbe teoricamente evolversi per includere la maggior parte di ciò che desideri. Sto cercando una misura pratica di possibilità. Questo conflitto con altre caratteristiche? L'implementazione è abbastanza semplice da funzionare correttamente con JVM? E anche, è una buona idea?

    
posta Nicole 19.02.2011 - 01:32
fonte

4 risposte

14

Ecco una risposta di otto pagine alla tua domanda: link

Se posso provare a riepilogare grossolanamente i problemi con l'aggiunta di pigrizia, sono i casi d'angolo. Ci sono molti avvertimenti in merito agli effetti collaterali. Considera, nel tuo esempio, se il costruttore avesse effetti collaterali visibili come il bump di un contatore globale o l'I / O ... È difficile ragionare su quando accadrebbe. O considera ancora più brutti effetti collaterali sulle eccezioni (vengono lanciati ... quando fai riferimento all'oggetto pigro?)

Basta saltare alla sezione 6 del documento sopra. (E ammira tutta la logica formale del sistema di tipi sulle pagine che salti ...)

    
risposta data 27.09.2011 - 09:05
fonte
10

Ovviamente è eminentemente possibile. Infatti, scala ha già esattamente questa funzione! (Scala è un linguaggio JVM e compila fino al bytecode). Ecco un frammento di sorgente:

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

Ed ecco come appare una forma intermedia del codice compilato:

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

}

    
risposta data 27.09.2011 - 12:58
fonte
6

Penso che prima sia necessario aggiungere proprietà reali al linguaggio Java, piuttosto che fare affidamento sull'idioma getX / setX. In questo modo puoi semplicemente contrassegnare la proprietà come pigra (e sincronizzata, sola, ecc ...).

Ordina cosa viene richiesto qui (Objective-C, ma il concetto si applica).

    
risposta data 19.02.2011 - 20:14
fonte
0

Ovviamente questo potrebbe essere aggiunto a Java, la parola chiave lazy potrebbe essere implementata come zucchero sintattico. Tuttavia, se verrà implementato dipende dalla visione dei compilatori del compilatore.

    
risposta data 19.02.2011 - 19:51
fonte