26869


なぜ`this()` `super()`は先頭に以外に記述することをなぜ禁止したのでしょうか？  
`this()`や`super()`を呼び出す前に何かをしないといけない時は面倒じゃないですか。  
なぜなのでしょうか。

[code]

    public class Instance{
      String name;
      public Instance(){
        //ここに処理があるとエラーが出る
        this("Sample");
      }
      public Instance(String name){
        //処理…
      }
    }
    
[/code]

`Instance instance=getInstance();`みたいにする方法もあります。

[code]

    public class Instance{
      String name;
      public static Instance getInstance(){
        //処理
        return new Instance("Sample");
      }
      private Instance(String name){
        //処理…
      }
    }
    
[/code]

それでいいのですが、少し気になったので教えて下さい。


CC BY-SA 3.0
2016-06-19T13:04:52.750
26867
2016-06-21T03:01:07.620
2016-06-21T03:01:07.620
15185
15185
question
java
コンストラクタの this() super()はなぜ先頭にしか記述出来ないか


この制約は、正しくはコンストラクタのみにあります。

> call to super() must be first statement in constructor.

のエラーメッセージの通り、まだ生成されていない不定状態のオブジェクトへアクセスされてしまうことを防ぐためです。

以下のような状況を考えるとわかりやすいです。

[code]

    class Instance {
        protected String name;
        public Instance() {
            this("BaseType");
        }
        public Instance(String name) {
            this.name = name;
        }
    }
    
    class SubInstance extends Instance {
        public SubInstance() {
            this.name = "SubType";
            super(); // Illegal Code
        }
    }
    
[/code]

`SubInstance`の`super()`呼び出しタイミングでは、まだ`Instance`のコンストラクタは実行されていません。

この不正なコードでは、`SubInstance`の冒頭で`name`フィールドを`SubType`に書き換えていますが、もしその後に`super()`呼び出しによる初期化ができたとすると、`name`フィールドは`BaseType`で上書きされてしまいます。

想定しないフィールドの値になるだけなら大したことはないと思うかもしれません。しかし、まだ初期化されていないために`null`の参照にアクセスできてしまった場合はどうでしょうか？

同じことが`this()`でも言えるのが分かると思います。


CC BY-SA 3.0
2016-06-19T14:12:10.893
26869
2016-06-19T14:12:10.893
5337
26867
answer


少なくとも、自分や親が定義したインスタンスメソッドをコンストラクタの処理で使えるようにするため、という理由があると思います。

[code]

    public class Instance{
      String name;
      public Instance(){
        this("Sample");
        meth();
      }
      public Instance(String name){
        //処理…
      }
      public void meth() {
      }
    }
    
[/code]

これが理由だとすると当該オブジェクトとは独立な処理（`System.out.println()`やスタティックメソッド呼出し）は書いてあっても良さそうですが、これをコンパイラが判定するのは難しいのではないかと思います。そしてそれこそ`getInstance`の方法が使える場面です。


CC BY-SA 3.0
2016-06-19T14:32:59.823
26870
2016-06-19T14:32:59.823
13199
26867
answer