投稿

5月, 2008の投稿を表示しています

Effective Java Second Editionが届きました。

イメージ
予約してから1ヶ月待たされてました。それが今日amazonからやっと届きました。 明日はJavaOne報告会に行ってきます。 ITProの記事で櫻庭祐一氏が書かれているJava 7情報。 同氏のJavaSE最新情報が聞けるので、期待して行ってきます。    

Java Genericsが難しい(4)

3.ジェネリクスと可変長引数と継承 以下のコードをコンパイル,実行すると、実行時エラー(ClassCastException)になる。 class Plus {   R apply(T... t) {     return t[0] + t[1];   } } class Client {   public void main(String[] args) {     Plus <Integer,Integer> p = new Plus< Integer,Integer > ();     Integer result = p.apply(1,2);        :        :   } } 私はjad使ってイレイジャの処理を見ていたのですぐにわかったが、 ソースコードだけ見て原因を特定できる人はすごいと思う。 jadで逆コンパイルすると以下のコードになる。 class Plus {   Object apply(Ojbect[] t) {     return apply((Integer[]) t); //   }   Integer apply(Integer[] t) {     return t[0] + t[1];   } } class Client {   public void main(String[] args) {     Plus p = new Plus ();     Integer result =       p.apply(new Object[] {1,2}); //        :   } } イレイジャ処理で生成されたブリッジメソッドに対し、可変長引数の処理が 行われるためブリッジメソッド内部で無理やりキャストする処理でエラーになる。 ブリッジメソッド、可変長引数など自動生成されるコード内でのエラーのため これははまると解決が大変なエラーだと思う。 ということで可変長引数とジェネリクスの組み合わせは良くない組み合わせ だと思う。    

Java Genericsが難しい(3)

2.ジェネリクスとオーバーロード 既存の方法で、何とか演算処理をさせたく少し試してみた。 Genericsメソッド内から、型だけ異なるオーバーロードメソッドの 呼び出してみた。 class Plus T,R > implements Function T,R > {   R apply(T arg1, T arg2) {     return apply(arg1,arg2);   }   Integer apply(Integer arg1, Integer arg2) {     return arg1 + arg2;   }   Double apply(Double arg1, Double arg2) {     return arg1 + arg2;   } } 結果はコンパイルエラー。 イレイジャ処理でObject型になってしまうので、IntegerともDoubleとも 合わない適当なメソッドが無い、とコンパイラが文句言う。 そもそもこのコードがうまくいったとしても、折角Genericsを利用しているのに オーバーロードメソッド定義していたらGenerics使っている意味無いし。 (Genericsなんか使わずオーバーロードメソッドで十分と)    

java7のBigDecimalの演算子オーバーロードに関する希望

「わんくま同盟」の方のサイトにあったC#の例のような、 演算子ラッパーメソッドとか提供されるとうれしいな。 java7が以下のような感じの実装とか希望。 abstract class Operator extends Number {   T add( T t){} // +   T negate( T t){} // -   T divide( T t){} // /   T mulutipry( T t){} // *   T modify(T t){} // % } class Integer extends Operator {   ... } 上記のようなOperatorインタフェースを継承すると演算子で記述しても 以下のメソッドに展開し処理する仕組み希望。 コンパイラは以下のインタフェースを継承以外は演算子として解釈しない とか。 そしたらこんなファンクタ作れるかも? interface Function {   R apply(T); } class Plus implements Function {   R apply(T t) {     return t + t;   } } class Client {   public void main(String[] args) {     Loop.foreach(new Integer[] {1,2,3,4}, new Plus ());     Loop.foreach(new Double[] {1.1,2.2,3.3,4.4}, new Plus ());   } } jadでPlus.classファイル開くとこんなイメージ。 class Plus implements Function {   Object apply(Object t) {     return this.apply((Operator)t);   }   Operator apply(Operator t) {     return t.add(t);   } } だったらいいなあ。 大体、BigDecimalにある演算子のラッパーメソッドを他の プリミティブ型ラッパークラスに用意してくれれば、演算子オーバーロードはいらないのだけど。    

Java Genericsが難しい(2)

1.ジェネリクスと四則演算 以下のような記述がしたかったのだけど、javaではできません。(コンパイルエラー) C++Templateならこんな感じでもいけるはず。 class Plus < T extends Number,R extends Number >     implements Function < T,R > {   R apply(T arg1, T arg2) {     return arg1 + arg2;   } } ”このインタフェースを継承するとコンパイルのときboxing/unboxingが働くよ” というマーカーインタフェースがない(Numberクラスはダメ)ので、ジェネリクス型で 記述した変数に対し演算子を用いて演算することはできない。 「ジェネリクスと四則演算」の組み合わせはC#(.net)でも利用できないようで、 「わんくま同盟」の方のblogにその辺の記事をみかけた。 でも演算子オーバーロードのあるC#(.net)は将来に希望を持てそうでうらやましい。