3

コンストラクターが例外で終了した場合、オブジェクトは通常のオブジェクトとまったく同じように作成されますか?

class A {

    static A o;

    A() throws Exception {
        o=this;
        throw new Exception();
    }

    void f() { System.out.println("f(): entry."); };

    static public void main(String[]args ) {
        try {
         A o =new A();
        }
        catch (Exception e) {
              System.out.println("Exception: " + e);
        }

        A.o.f(); // Is it safe to use this object?
       }
}

これはコンパイルおよび実行され、このプログラムの出力は次のとおりです。

Exception: java.lang.Exception
f(): entry.
4

2 に答える 2

3

例外をキャッチした場合、構築されたオブジェクトが呼び出し元に戻されることはなく、呼び出し元の結果変数は設定されません。ただし、理論的には静的変数が設定されるため、アクセスできない理由はわかりません。

ただし、メソッド検証でthisはコンストラクターが呼び出されるまで保存できないsuperため、これは他の方法で保護されたオブジェクトへの「バックドア」ではないことに注意してください。

それはあなたの目的なので、「安全」はあなた次第です。

[もう少し詳しく:コンストラクターのコンパイル済みバージョンを入力すると、「生の」Javaオブジェクトが完全に構築されます。システムを有効にするために追加の作業は必要ありません。superただし、コンストラクターはまだ呼び出されていません。明示的に呼び出すsuperか、コンパイラーsuperにデフォルトで呼び出しを挿入させるかは、ユーザー次第です(明示的な呼び出しがない場合は、メソッドの開始時に実行されます)。 )。JVMの「バイトコードベリファイア」には、コンストラクターを呼び出す前にコンストラクターで何が発生するかについて非常に厳密なルールがあり、静的なものsuperに格納thisすることは間違いなくノーノーです。VerifyErrorが発生します。]

于 2012-05-18T03:21:30.857 に答える
2
 A.o.f(); // Is it safe to use this object?

これは、他のJavaオブジェクトと同じようにメソッド呼び出しに応答する通常のJavaオブジェクトです。Java言語に関する限り、これは未定義動作の原因ではありません。

それは安全に使用できるという意味ではありません。多くのクラスの安全性は、重要な不変条件を維持する能力に依存し、建設中または重要な操作中にスローされる予期しない例外は、多くの場合、それらの不変条件が保持されないため、安全に使用できないことを意味します。

Aをサブクラス化するとどうなるか考えてみましょう

public class S extends A {
  boolean dirty;

  S() throws Exception {
    // Do work to maintain important security invariants.
    dirty = true;
  }

  void foo() {
    if (dirty) {
      System.out.println("clean");
      dirty = false;
    }
    System.out.println("foo");
  }

  public static void main(String... argv) {
    try {
      new S();
    } catch (Exception ex) {}
    // Now A.o is an instance of S, but S's constructor
    // was never called.
    S s = (S) A.o;  // works.
    s.foo();  // Never prints clean before printing foo.
  }
}
于 2012-05-18T03:12:43.207 に答える