遅延初期化を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
知らないけど、コード例はスレッドセーフではない
Armand

2
@Alison synchronizedキーワードは、メソッドにある場合と同じように機能します。もっと複雑な工法の宿泊施設もあると思います。私の特定の使用例では、問題の性質上、すべてのリクエストが独自の世界であるため、同期しても意味がありません。
ニコール

C#では、Lazyはライブラリにありますが、言語でサポートされています。sankarsan.wordpress.com/2009/10/04/laziness-in-c-4-0-lazyt Javaにはラムダ、デリゲート、クロージャがありますか?ちなみに、あなたはSOでこれを尋ねたいので、Jon Skeet&co。彼らの知恵を共有することができます。
ジョブ

3
ほとんどすべての言語を組み込むことができます。しかし、複雑さの予算と機能リストは限られており、言語設計者は最も重要であると考えるもののみを含めることができます(ラリーウォールを除く-特にPerl 6別名「すべてのパラダイムは私たちに属しています」)。

1
基本的な問題は、Javaがメタプログラミング機能を持たない唯一の静的型付け言語であることです。Cでは、これをマクロとして10分で書くことができます。C ++では、これをテンプレートとして約2分で作成できます。Javaでは、貼り付けて変更できます。
kevin cline、2011

回答:


14

ここにあなたの質問への8ページの回答があります:http : //tinlizzie.org/~awarth/papers/fool07.pdf

怠惰の追加に関する問題をおおまかに要約して試すことができれば、それはコーナーケースです。副作用に関する多くの注意事項があります。あなたの例で、コンストラクターにグローバルカウンターのバンプやI / Oの実行などの目に見える副作用がある場合を考えてみます。または、例外に関する醜い副作用さえ考慮してください(遅延オブジェクトを参照すると例外がスローされますか?)

上記のペーパーのセクション6にスキップしてください。(そして、スキップしたページのすべての型システムの正式なロジックを賞賛してください...)


この論文はこの機能を扱っているので、この答えを受け入れる。ありがとう!
ニコール

TL; DRあなたがプログラムするとき、あなたは副作用を防ぐために何が起こるかを知る必要があります、怠惰で、これは本当に手に負えないでしょう。Hibernateを知っており、Hibernateでどれほど多くの問題が発生するかを理解している場合は、言語全体で同じように考えてみてください。
Walfrat 2017年

10

もちろん、それは非常に可能です。実際、scalaにはすでにこの機能が備わっています。(ScalaはJVM言語であり、バイトコードにコンパイルされます)。以下はscalaソースの一部です:

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でのPTの回答とどのように調和しますか?
Pacerier 2014年

6

getX / setXイディオムに依存するのではなく、最初に実際のプロパティをJava言語に追加する必要があると思います。そうすれば、プロパティを遅延(および同期、読み取り専用など)としてマークできます。

ここで求められていることの一種です(Objective-C、ただし概念が適用されます)。


0

もちろん、これをJavaに追加することもできます。lazyキーワードを構文糖として実装できます。ただし、実装されるかどうかは、コンパイラビルダーのビジョンに依存します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.