¿Hay alguna razón para que la inicialización diferida no se pueda incorporar a Java?

10

Como estoy trabajando en un servidor sin ningún estado no persistente para los usuarios, cada objeto relacionado con el usuario que tenemos se implementa en cada solicitud.

En consecuencia, a menudo me encuentro haciendo una inicialización perezosa de las propiedades de los objetos que pueden no utilizarse.

protected EventDispatcher dispatcher = new EventDispatcher();

Se convierte ...

protected EventDispatcher<EventMessage> dispatcher;

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

¿Hay alguna razón para que esto no se pueda incorporar a Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


Como se menciona a continuación en los comentarios, me doy cuenta de que un lenguaje podría evolucionar teóricamente para incluir casi todo lo que desee. Estoy buscando una medida práctica de posibilidad. ¿Estaría en conflicto con otras características? ¿Es la implementación lo suficientemente simple como para funcionar bien con la JVM tal como existe? E incluso, ¿es una buena idea?

Nicole
fuente
2
dunno pero el código ejemplo no es thread-safe
Armand
2
@Alison la synchronizedpalabra clave funcionaría igual que si estuviera en el método. Me imagino que habría algún alojamiento de métodos de construcción más complicados. En mi caso de uso específico , debido a la naturaleza del problema, con cada solicitud como su propio mundo, sincronizado no tiene sentido.
Nicole
En C # Lazy está en una biblioteca, pero es compatible con el lenguaje. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt ¿Java tiene lambdas y delegados y cierres? Por cierto, quieres preguntar esto en SO, para que Jon Skeet & co. Pueden compartir su sabiduría.
Trabajo
3
Puedes construir casi todo en cualquier idioma. Pero el presupuesto de complejidad y la lista de características son limitados y los diseñadores de idiomas solo pueden incluir lo que consideran más importante (bueno, excepto Larry Wall, especialmente en Perl 6, también conocido como "Todos sus paradigmas nos pertenecen").
1
El problema fundamental es que Java es aproximadamente el único lenguaje tipado estáticamente que no tiene una función de metaprogramación. En C podrías escribir esto como una macro en diez minutos. En C ++, podría escribir esto como una plantilla en aproximadamente dos minutos. En Java puedes ... pegar y modificar.
Kevin Cline

Respuestas:

14

Aquí hay una respuesta de ocho páginas a su pregunta: http://tinlizzie.org/~awarth/papers/fool07.pdf

Si puedo tratar de resumir groseramente los problemas para agregar pereza, es el caso de la esquina. Hay muchas advertencias sobre los efectos secundarios. Considere, en su ejemplo, si el constructor tuvo efectos secundarios visibles como golpear un contador global o hacer E / S ... Es difícil razonar cuándo ocurriría eso. O considere efectos secundarios aún más feos sobre las excepciones (se lanzan ... cuando hace referencia al objeto perezoso?)

Simplemente salte a la sección 6 en el documento anterior. (Y admire toda la lógica formal del sistema de tipos en las páginas que omite ...)

PT
fuente
Aceptando esta respuesta debido a la profundidad que el documento aborda esta característica. ¡Gracias!
Nicole
TL; DR cuando programa tiene que saber qué sucede para prevenir los efectos secundarios, con pereza, esto realmente puede pasar desapercibido. Si conoce Hibernate y la cantidad de problemas que algunas personas tienen con él, imagine lo mismo para todo el idioma.
Walfrat
10

Por supuesto que es eminentemente posible. De hecho, ¡ scala ya tiene exactamente esta característica! (Scala es un lenguaje JVM y se compila en bytecode). Aquí hay una fuente de scala:

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

Y así es como se ve una forma intermedia del código compilado:

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
fuente
Entonces, ¿cómo conciliaría esto con la respuesta de PT en programmers.stackexchange.com/a/110958/24257 ?
Pacerier
6

Creo que primero debe agregar propiedades reales al lenguaje Java, en lugar de confiar en el idioma getX / setX. De esa manera, podría marcar la propiedad como perezosa (y sincronizada, de solo lectura, etc.).

Más o menos lo que se pide aquí (Objetivo-C, pero se aplica el concepto).

Martin Wickman
fuente
0

Por supuesto, esto podría agregarse a Java, la palabra clave perezosa podría implementarse como azúcar sintáctica. Sin embargo, si se implementará depende de la visión de los compiladores del compilador.

Michiel Overeem
fuente