2010年10月02日

[java]で、匿名クラス?

で、モヤモヤの原因、匿名クラス。
GWTとかWicketで頻用している割に、理解は漫然としていたので調査。

※ソースは後述

<Test1>

(1)匿名クラスのインスタンス初期化ブロック使用

矢野さんのカッコイイ方式ですね。

Test1 ts2 = new Test1() {{a = "instance AAA"; b = "instance BBB";}};

...これは、代入式使ってるからカッコ良くないけど(笑)

(2)元クラスのprivateにはアクセスできない

Test1 ts3 = new Test1() {{a = "instance AAA"; b = "instance BBB"; c = "instance CCC";}};

private String cにアクセスしようとすると、当然怒られる。

(3)元クラスのメソッドのオーバーライド

Test1 ts4 = new Test1() {{a = "instance AAA"; b = "instance BBB";} String getD() {return "ddd";}};

...当然に問題ない。

(4)元クラスのインスタンス初期化ブロックのオーバーライド(super)

Test1 ts5 = new Test1() {{super();}};

無理...つか元々、継承側で元の初期化ブロックのオーバーライドとか出来ないのかな。
(やりたいなら継承側の初期化ブロックなりコンストラクタで変えればすむ話か...)

(5)匿名クラスでフィールド・メソッド実装&外部からの呼出

Test1 ts6 = new Test1() {String e; {e = "instance E";} String getD() {return super.getD() + "☆" + getE();} public String getE(){ return e;}};

匿名クラスでフィールド・メソッドの実装は可能(これも当然)だけど、これを外部から呼び出すのは無理。

#もしかすると方法はあるのかもしれないけど、そんなことする必要があるなら最初から普通のクラスにするべきだろう。

<TestIF>

インターフェース、抽象クラスのメソッドの実装

どちらかというと、これが匿名クラスの存在理由の大きな理由だろうねぇ。


結論。匿名クラスとは「クラス(抽象含む)・インターフェースのお手軽な継承実装インスタンス生成機構」って所ですかね〜(←長ったらしいから今後も「匿名クラス」って言うけど)。
いちいちイベント実装全てにキチンとクラス作ってインスタンス生成してね☆とか言われたら面倒で死ねるので、ないと困るけど。まぁ「気持ち悪い」と感じる人がいるのは理解できますね〜。

自分?一気にインスタンスまで生成してくれると思えばキモさは消えました。今後もバンバン使います(笑)

思うに「匿名クラス」って響きから「クラスが」動くような気がしてくるから気持ち悪さが残るのではないかなぁ。(アタマではインスタンスに決まってる!と思っても、Hoge h = new Hoge() {(...クラス実装...)}ってソースを見ながら「匿名クラス」って言われると...)

<Test1>

public class Test1 {
public String a = "a";
public String b = "b";
private String c = "c";
String d = "d";

String getD() {
return d;
}

public static void main(String[] args) {
// (1)匿名クラスのインスタンス初期化ブロック使用
System.out.println("--- ts2 ---");
Test1 ts2 = new Test1() {{a = "instance AAA"; b = "instance BBB";}};
System.out.println(ts2.a);
System.out.println(ts2.b);
System.out.println(ts2.c);
System.out.println(ts2.d);

// (2)元クラスのprivateにはアクセスできない
System.out.println("--- ts3 ---");
//Test1 ts3 = new Test1() {{a = "instance AAA"; b = "instance BBB"; c = "instance CCC";}};
//System.out.println(ts2.a);
//System.out.println(ts2.b);

// (3)元クラスのメソッドのオーバーライド
System.out.println("--- ts4 ---");
Test1 ts4 = new Test1() {{a = "instance AAA"; b = "instance BBB";} String getD() {return "ddd";}};
System.out.println(ts4.a);
System.out.println(ts4.b);
System.out.println(ts4.c);
System.out.println(ts4.d);
System.out.println(ts4.getD());

// (4)元クラスのインスタンス初期化ブロックのオーバーライド(super)
System.out.println("--- ts5 ---");
/*
Test1 ts5 = new Test1() {{super();}};
System.out.println(ts5.a);
System.out.println(ts5.b);
System.out.println(ts5.c);
System.out.println(ts5.d);
System.out.println(ts5.getD());
*/

// (5)匿名クラスでフィールド・メソッド実装&外部からの呼出
System.out.println("--- ts6 ---");
Test1 ts6 = new Test1() {
String e;
{
e = "instance E";
}

String getD() {
return super.getD() + "☆" + getE();
}

public String getE(){
return e;
}
};
System.out.println(ts6.a);
System.out.println(ts6.b);
System.out.println(ts6.c);
System.out.println(ts6.d);
System.out.println(ts6.getD());
//System.out.println(ts6.getE());
System.out.println(ts6.getClass());
//System.out.println(((TestStatic$3)ts6).getE());
}
}




<TestIF>

public class TestIF {
interface HogeIF {
String hogetter(String hoge);
}

abstract class HogeAbst {
abstract String hogett(String hoge);
}

public static void main(String[] args) {
// IFの匿名クラス
System.out.println("--- IFの匿名クラス ---");
HogeIF hif = new HogeIF() {
public String hogetter(String hoge) {
return hoge + "☆HogeIF";
}
};
System.out.println(hif.hogetter("ほげった〜"));

// 抽象クラスの匿名クラス
System.out.println("--- 抽象クラスの匿名クラス ---");
HogeAbst habst = new TestIF().new HogeAbst() {
String hogett(String hoge) {
return hoge + "☆HogeAbst";
}
};
System.out.println(habst.hogett("ほげっと"));
}

}


ラベル:java
posted by ありい at 19:54| Comment(0) | TrackBack(0) | java | このブログの読者になる | 更新情報をチェックする

[java]匿名クラス...の前に初期化ブロックのまとめ

javaの匿名クラスの理解が曖昧で、モヤモヤしていたので調査。
主に矢野勉さんのページを参考に実験。で、匿名クラスの前に初期化ブロックの初期化順序のメモ。

(1)static変数の代入
(2)static初期化ブロック
(3)instance変数の代入
(4)instance初期化ブロック
(5)コンストラクタ


public class Test1 {
// (1)staticとして[1]
static public String sa = "sa";
static public String sb = "sb";

// (2)staticとして[2]
static {
sa = "static A";
//sb = "static B";
}

// (3)instanceとして[1]
public String a = "a";
public String b = "b";
private String c = "c";
String d = "d";

// (4)instanceとして[2]
{
a = "instance A";
//b = "instance B";
c = "instance C";
//d = "instance D";
}

// (5)instanceとして[3]
Test1() {
//a = "instance AA";
b = "instance BB";
c = "instance CC";
}

public static void main(String[] args) {
System.out.println("--- static ---");
System.out.println(sa);
System.out.println(sb);

// 普通のinstanceとして
System.out.println("--- ts1 ---");
Test1 ts1 = new Test1();
System.out.println(ts1.a);
System.out.println(ts1.b);
System.out.println(ts1.c);
System.out.println(ts1.d);
}
}

ラベル:java
posted by ありい at 18:35| Comment(0) | TrackBack(0) | java | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。