this.getClass()
オブジェクトの構築中にJavaは何を返しますか(例えば、コンストラクターまたはフィールド初期化子式から呼び出された場合)。最も派生したクラスが返されることを期待しても安全ですか?
これは、Java言語でのオブジェクトの構築とJava仮想マシンでのオブジェクトの構築の違いを観察できるいくつかの場所の1つです。
JVMバイトコードでは、特定のタイプのオブジェクトの作成は単一の命令であるため、アトミックです。オブジェクト自体がスーパータイプのような別のタイプのオブジェクトになることは決してありません。ただし、このオブジェクトはまだ「構築」されていません。バイトコードレベルでは、コンストラクターはという名前の特別なメソッド<init>
であり、フィールドを設定したり、既存のオブジェクトを操作したりできます。
コンパイラーは、実際のコンストラクターに加えて、フィールド初期化子とインスタンス初期化子ブロックを<init>
メソッドにアセンブルします。の最初の操作<init>
は通常<init>
、スーパータイプで宣言された対応するメソッドを呼び出すことです。したがって、イニシャライザはスーパータイプからサブタイプへと順番に実行されます。ただし、スーパータイプ<init>
メソッドが実行されているとき、オブジェクト自体はすでに完了しているタイプです。したがってgetClass()
、そのタイプが返され、によって返される値はgetClass()
、それが呼び出される場所に応じて変化しません。
Java言語の観点から見ると、これは(ほとんど)問題点です。<init>
関係するメソッドのいずれかが例外をスローすると、オブジェクトは通常すぐにガベージコレクションの対象になります。ただし、部分的に構築されたオブジェクトを別のスレッドから見えるようにすることができるいくつかのケースがあります。その場合、一貫性のない状態のオブジェクトを観察できます。また、そのクラスを公開するJVMで<init>
(意図的に文書化されていない)メソッドを使用して、オブジェクトを実行せずに意図的に作成することもできますsun.misc.Unsafe
。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加