Gibt es einen Grund, warum eine verzögerte Initialisierung nicht in Java integriert werden konnte?

10

Da ich auf einem Server arbeite, auf dem Benutzer absolut keinen dauerhaften Status haben, wird jedes benutzerbezogene Objekt, das wir haben, bei jeder Anforderung bereitgestellt.

Infolgedessen mache ich häufig eine verzögerte Initialisierung von Eigenschaften von Objekten, die möglicherweise nicht verwendet werden.

protected EventDispatcher dispatcher = new EventDispatcher();

Wird...

protected EventDispatcher<EventMessage> dispatcher;

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

Gibt es einen Grund, warum dies nicht in Java integriert werden konnte?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


Wie unten in den Kommentaren erwähnt, ist mir klar, dass sich eine Sprache theoretisch so entwickeln könnte, dass sie fast alles enthält, was Sie wollen. Ich suche eine praktische Messung der Möglichkeit. Würde dies mit anderen Funktionen in Konflikt stehen? Ist die Implementierung einfach genug, um mit der vorhandenen JVM gut zu funktionieren? Und selbst, ist es eine gute Idee?

Nicole
quelle
2
Keine Ahnung, aber Beispielcode ist nicht threadsicher
Armand
2
@Alison Das synchronizedSchlüsselwort würde genauso funktionieren wie in der Methode. Ich stelle mir vor, dass es einige kompliziertere Bauweisen geben würde. In meinem speziellen Anwendungsfall ist die Synchronisierung aufgrund der Art des Problems bei jeder Anforderung als eigene Welt sinnlos.
Nicole
In C # befindet sich Lazy in einer Bibliothek, wird jedoch von der Sprache unterstützt. sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Hat Java Lambdas und Delegierte und Schließungen? Übrigens möchten Sie dies auf SO fragen, damit Jon Skeet & Co. können ihre Weisheit teilen.
Job
3
Sie können so ziemlich alles in jede Sprache einbauen. Das Komplexitätsbudget und die Funktionsliste sind jedoch begrenzt, und die Sprachdesigner können nur das angeben, was sie für am wichtigsten halten (außer Larry Wall - insbesondere in Perl 6, auch bekannt als "Alle Ihre Paradigmen gehören uns").
1
Das grundlegende Problem ist, dass Java die einzige statisch typisierte Sprache ohne Metaprogrammierfunktion ist. In C können Sie dies in zehn Minuten als Makro schreiben. In C ++ können Sie dies in etwa zwei Minuten als Vorlage schreiben. In Java können Sie ... einfügen und ändern.
Kevin Cline

Antworten:

14

Hier ist eine achtseitige Antwort auf Ihre Frage: http://tinlizzie.org/~awarth/papers/fool07.pdf

Wenn ich versuchen kann, die Probleme mit dem Hinzufügen von Faulheit grob zusammenzufassen, dann sind es die Eckfälle. Es gibt viele Vorbehalte gegen Nebenwirkungen. Stellen Sie sich in Ihrem Beispiel vor, der Konstruktor hätte sichtbare Nebenwirkungen wie das Anstoßen eines globalen Zählers oder das Ausführen von E / A ... Es ist schwer zu überlegen, wann dies passieren würde. Oder betrachten Sie noch hässlichere Nebenwirkungen bei Ausnahmen (sie werden ausgelöst ... wenn Sie auf das faule Objekt verweisen?)

Fahren Sie einfach mit Abschnitt 6 im obigen Dokument fort. (Und bewundern Sie die gesamte formale Logik des Typsystems auf den Seiten, die Sie überspringen ...)

PT
quelle
Akzeptieren dieser Antwort aufgrund der Tiefe, in der das Papier diese Funktion behandelt. Vielen Dank!
Nicole
TL; DR Wenn Sie programmieren, müssen Sie wissen, was passiert, um Nebenwirkungen zu verhindern. Mit Faulheit kann dies wirklich unhandlich werden. Wenn Sie den Ruhezustand kennen und wissen, wie viel Ärger einige Leute damit haben, stellen Sie sich dasselbe für die gesamte Sprache vor.
Walfrat
10

Natürlich ist es hervorragend möglich. In der Tat hat Scala bereits genau diese Funktion! (Scala ist eine JVM-Sprache und wird bis zum Bytecode kompiliert.) Hier ist ein Stück Scala-Quelle:

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

Und so sieht eine Zwischenform des kompilierten Codes aus:

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
quelle
Wie würde dies mit der Antwort von PT unter programmers.stackexchange.com/a/110958/24257 in Einklang gebracht werden ?
Pacerier
6

Ich denke, Sie müssen zuerst der Java-Sprache echte Eigenschaften hinzufügen, anstatt sich auf die getX / setX-Sprache zu verlassen. Auf diese Weise können Sie die Eigenschaft einfach als faul markieren (und synchronisiert, schreibgeschützt usw.).

Sortieren von dem, was gefragt hier (Objective-C, aber Konzept gilt).

Martin Wickman
quelle
0

Natürlich könnte dies zu Java hinzugefügt werden, das Schlüsselwort faul könnte als syntaktischer Zucker implementiert werden. Ob es implementiert wird, hängt jedoch von der Vision der Compiler-Builder ab.

Michiel Overeem
quelle