JCIPのセクション3.2.1「安全なコンストラクタの使用法」では、コンストラクタからの別のスレッドに「をリークすることに対する警告があります。たとえパブリケーションがコンストラクタの最後のステートメントであっても」です。その最後の部分は私には強すぎるように思えますし、それは正当化されていません。工事の後に何が起こるのですか?私は避けるように注意しなければなりません。例外はありますか?私は最近、私がこのことをやったいくつかのコードを提出したので、私は興味があります。私は、リファクタリングして戻ってくる正当性があるかどうかを決めたいと思っています。java:なぜこれをコンストラクタからエスケープできないようにする必要がありますか?
答えて
Javaメモリモデルに関する限り、コンストラクタ出口は最終フィールドのセマンティクスで役割を果たします。したがって、コンストラクタが終了する前か後であるかに違いがあります。
This works This doesn't work
-------------------------------------------------------------
static Foo shared; static Foo shared;
class Foo class Foo
{ {
final int i; final int i;
Foo() Foo()
{ {
i = 1; i = 1;
shared = this;
} }
} }
shared = new Foo(); new Foo();
は(注:shared
は揮発性ではなく、出版物は、データ競合を介してである)
2つの実施例の間の唯一の違いは、コンストラクタの出口の前または後shared
を割り当てています。 2番目の例では、割り当て後にi=1
の順序を変更することができます。
ただし、パブリケーションが同期アクション(例:揮発性の変数を通して、それは大丈夫です。他のスレッドは完全に初期化されたオブジェクトを観察します。フィールドはfinal
する必要はありません。
データレース(またはデータレースを通じて何かを行うこと)は、非常に慎重な推論が必要な非常にトリッキーなビジネスです。データ競争を避ければ、事態はずっと簡単になります。 コードにデータレースが含まれていない場合は、コンストラクタが終了する直前にthis
がリークすることと、コンストラクタが終了した直後にパブリッシュすることに違いはありません。
いつでもコンストラクタから "最後のステートメントの[...]"を漏らすべきではありません。 this
は完全に構築されていないので、非常に奇妙なことが起こる可能性があります。非常によく似た質問については、this SO answerを参照してください。
あなたはそれがコンストラクタの最後の行だ場合でも、これを行うべきではありません
一つの理由は、JVMが許可されていることである(「this
漏れ」として知られている)コンストラクタのうち、this
を渡すことはありません現在のスレッドへの影響が影響を受けていない限り、ステートメントを並べ替えることができます。 this
が別のスレッドで実行されているプロセスに渡された場合、並べ替えを行うと奇妙で微妙なバグが発生する可能性があります。
別の理由は、サブクラスが独自の初期化を提供する可能性があるため、クラスのコンストラクタの最後の行で構築が完了しないことがあります。
- 1. なぜJavaソースファイルでUnicodeをエスケープする必要がありますか?
- 2. セレンページオブジェクト:なぜこれを返す必要がありますか?
- 3. なぜcrcを反転させる必要がありますか?どのような場合にはこれを行う必要がありますか?
- 4. なぜエンティティに空のコンストラクタを宣言する必要がありますか?
- 5. なぜ複数のコンストラクタを使用する必要がありますか?
- 6. Java 6が必要なアプレットはどこにありますか?
- 7. なぜmochaはdevDependenciesになる必要がありますか?
- 8. LinkedListなぜここにダミーを作成する必要がありますか?
- 9. なぜこれらのオブジェクトをリリースする必要はありませんか?
- 10. matches()でjava正規表現をエスケープする必要がありますか?
- 11. Javaでこれらのクラスをネストする必要がありますか?
- 12. なぜopengl32.libにリンクする必要がありますか
- 13. なぜhtml_safeに注意する必要がありますか?
- 14. C#コンストラクタのようなJavaコンストラクタを作成できますか?
- 15. Javaでは、例外クラスが必要になる前にクラスローダーが使用できるようにする必要があるのはなぜですか?
- 16. なぜvalue.lengthを使用する必要がありますか?
- 17. なぜPOSTデータをネストする必要がありますか?
- 18. なぜredux-thunksをディスパッチする必要がありますか?
- 19. なぜメッセージハブをポーリングする必要がありますか?
- 20. なぜ変数をリセットする必要がありますか?
- 21. なぜデータベースラッパーを作成する必要がありますか?
- 22. Reflect.construct()なぜオブジェクトプロトタイプをオーバーライドする必要がありますか?
- 23. なぜレンダリングをカウントする必要がありますか?
- 24. なぜstopPropagation()を使用する必要がありますか?
- 25. なぜ/きれいなターゲットが必要なのですか?
- 26. Javaクラスにコンストラクタがないとどうなりますか?
- 27. 移動コンストラクタはnoexceptである必要がありますか?
- 28. コンストラクタから呼び出すと、ランダムオブジェクトを静的にする必要があるのはなぜですか?
- 29. なぜこのコードで(フラッシュする)必要がありますか?
- 30. なぜこのコードでキャストする必要がありますか?
http://msmvps.com/blogs/jon_skeet/archive/2010/09/02/don-t-let-this-get-away.aspx – SLaks