10

Since I'm working on a server with absolutely no non-persisted state for users, every User-related object we have is rolled out on every request.

Consequently I often find myself doing lazy initialization of properties of objects that may go unused.

protected EventDispatcher dispatcher = new EventDispatcher();

Becomes...

protected EventDispatcher<EventMessage> dispatcher;

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

Is there any reason this couldn't be built into Java?

protected lazy EventDispatcher dispatcher = new EventDispatcher();


As mentioned below in the comments, I realize a language could theoretically evolve to include most anything you want. I'm looking for a practical measurement of possibility. Would this conflict with other features? Is the implementation simple enough to work well with the JVM as it exists? And even, is it a good idea?

Nicole
  • 28,111
  • 12
  • 95
  • 143
  • 2
    dunno but example code isn't thread-safe – Armand Feb 19 '11 at 02:03
  • 2
    @Alison the `synchronized` keyword would work the same as if it was on the method. I imagine there would be some accomodation of more complicated construction methods. In my *specific* use case, due to the nature of the problem, with every request as it's own world, synchronized is pointless. – Nicole Feb 19 '11 at 02:09
  • In C# Lazy is in a library, but it is supported by the language. http://sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt/ Does Java have lambdas and delegates and closures? By the way, you do want to ask this on SO, so that Jon Skeet & co. can share their wisdom. – Job Feb 19 '11 at 04:25
  • 3
    You can build pretty much everything into any language. But complexity budget and feature list are limited and the language designers can only include what they consider most important (well, except Larry Wall - especially in Perl 6 aka "All your paradigms are belong to us."). –  Feb 19 '11 at 11:43
  • Have you considered AOP? AspectJ has everything you need to do that. – Laurent Pireyn Feb 19 '11 at 17:18
  • @delnan, I'm going for a more practical measurement of *possibility* than a wild-eyed pie-in-the-sky wishlist. Like, would this conflict with other features? Is the implementation simple enough to work well with the JVM as it exists? etc. – Nicole Feb 19 '11 at 19:21
  • 1
    The fundamental problem is that Java is about the only statically typed language with no meta-programming facility. In C you could write this as a macro in ten minutes. In C++ you could write this as a template in about two minutes. In Java you can ... paste and modify. – kevin cline Sep 27 '11 at 07:29

4 Answers4

15

Here is an eight page answer to your question: http://tinlizzie.org/~awarth/papers/fool07.pdf

If i can try and coarsely summarize the problems with adding laziness, it's the corner cases. There are a lot of caveats around side-effects. Consider, in your example, if the constructor had visible side-effects like bumping a global counter or doing I/O... It's hard to reason about when that would happen. Or consider even uglier side-effects about exceptions (they're thrown ... when you reference the lazy object?)

Just skip to section 6 in the above paper. (And admire all the type system formal logic on the pages you skip ...)

Matthew Flynn
  • 13,345
  • 2
  • 38
  • 57
P.T.
  • 386
  • 2
  • 4
  • Accepting this answer due to the depth that the paper addresses this feature. Thanks! – Nicole Oct 03 '11 at 18:02
  • TL;DR when you program you have to know what happens to prevent side-effects, with lazyness, this can really get ouf of hand. If you know Hibernate and how much trouble some people have with it, just imagone the same for the whole language. – Walfrat Mar 09 '17 at 08:51
10

Of course it is eminently possible. In fact, scala already has exactly this feature! (Scala is a JVM language and compiles down to bytecode). Here is a piece of scala source:

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

And here is what an intermediate form of the compiled code looks like:

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
  • 1,227
  • 8
  • 15
  • So how would this reconcile with P.T.'s answer at http://programmers.stackexchange.com/a/110958/24257 ? – Pacerier Jun 25 '14 at 04:38
6

I think you first need to add real properties to the Java langauge, rather than relying on the getX/setX idiom. That way you could just mark the property as lazy (and synchronized, readonly etc...).

Sort of what is asked for here (Objective-C, but concept applies).

Martin Wickman
  • 13,305
  • 3
  • 31
  • 66
0

Of course this could be added to Java, the keyword lazy could be implemented as syntactic sugar. However, wether it will be implemented depends on the vision of the compiler builders.

Michiel Overeem
  • 196
  • 1
  • 4