トップ «前の日記(2004-04-05) 最新 次の日記(2004-04-07)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2004-04-06

_ 風は冷たいが天気は良い

よく眠ってないので、なお眠い。

_ ちょっとイヤ(内部クラスは仮想化が甘いと思う)

Javaは、すべてのメソッドが仮想化されていると考えていたが、インナークラス(追記:のコンストラクタ)については静的な評価が行われるようだ。きっと仕様を確認すればそう書いてあるんだろうが(今はその余裕が無いので後回し)これは直観的では無い。
// O1.java
package com.example;
public class O1 {
    public void hello() {
	System.out.println("hello!");
    }
    public class I1 {
	public void hello() {
	    System.out.println("hello");
	}
    }
}
に対して
//O2.java
package com.example;
public class O2 extends O1 {
    public void hello() {
	System.out.println("hell!");
    }
    public class I1 extends O1.I1 {
	public void hello() {
	    System.out.println("hell");
	}
    }
}
に対するクライアント
// Oc.java
 package com.example;
public class Oc {
    public static void main(String[] args) {
	O1 o = new O2();
	o.hello();	 // 仮想化されているのでhell!
	O1.I1 in = o.new I1();
	in.hello();
	in = ((O2)o).new I1();
	((O2)o).hello(); // 当然hell!
	in.hello();
    }
}
コメントの通り、メソッドについてはO2のメソッドが呼び出される。
しかし、インナークラスのコンストラクタは、呼び出したインスタンスの静的なクラスの宣言が参照される。
と、ここまで書いて気づいたが、同名staticメソッドはどうなるんだ? それと同じ扱いってことかな? でも、インナークラスのコンストラクタは明示的にインスタンスに依存したメソッドなのだが(だから、インスタンス.newという構文)。
上の出力は以下のとおり。
~/test>java com.example.Oc
hell!
hello
hell!
hell
~/test>
最初の呼び出しで作成されるのは、O1$I1のほうで、呼び出したインスタンスoの静的な宣言に従っている。
っていうか、1時間ほどハマった。
追記:書いたらわかったが、クラスのコンストラクタを呼び出すわけだからクラス名が必要となり、かつそのクラスはコンパイル時に評価せざるを得ないわけだから、呼び出しクラスの静的な宣言が有効なのは、ある意味当然ではある。が、静的に解決させずに実行時にインスタンスのクラス名からコンストラクタを呼ぶっていうのがあっても良いような気も。その場合には、ファクトリメソッドを作っとけばいいのか……

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|

ジェズイットを見習え