2011年3月23日水曜日

[Java]戻り値が異なる引数の同じオーバーロード

Javaでは、メソッドのオーバーロードという機能があり、引数の型または数の異なる同じ名前のメソッドを定義することができます。
しかし、引数が同じで、戻り値が異なる。というメソッドの定義はできません。と思っていたんですが、スタティックなメソッドの場合のみ、そうじゃないということを最近知りました。
人の書いたコードレビューって、こういう発見があって楽しいですね!。で、コード例は以下のとおり。

class TestApp {

    public static void main(String[] args) {
        System.out.println("TEST1=" + BaseClass.getInstance());
        System.out.println("TEST2=" + SubClass.getInstance());
    }

    static class BaseClass{
        private static BaseClass instance1 = new BaseClass();
        public static BaseClass getInstance(){return instance1;}
        public String toString() {
            return getClass().getName();
        }
    }

    static class SubClass extends BaseClass{
        private static SubClass instance2 = new SubClass();
        //staticの場合は、引数違いのオーバーロードが可能!
        public static SubClass getInstance(){return instance2;}
        public String toString() {
            return getClass().getName();
        }
    }
}


■結果
TEST1=TestApp$BaseClass
TEST2=TestApp$SubClass

2011年3月18日金曜日

[Android]USBドライバ(その2)

GDD Blog: [Android]USBドライバで備忘を書きましたが、なんとベンダIDを書いておけば、デバッグドライバすべてOK的なことがUsing Hardware Devicesに書かれています。
でも、Windowsのばあい、どこにファイルを置けばいいのかよくわかりません。でgoogleで調べてみるとWindowsでは、
 /ユーザフォルダ/.android/adb_usb.ini
に書いておけばよい的なことが書かれていたのでやってみました。がうまくいかず。
よくよく↑のサイトをよく見ると、「If you're developing on Windows, you need to install a USB driver for adb.」と書かれています、直訳すると「Windows上で開発している場合は、ADBのUSBドライバをインストールする必要があります。」いやー直訳でもはっきりわかりますねぇ。
ということで、OEM USB DriversにOEMのドライバ一覧があったので、備忘代わりにメモ。

2011年3月14日月曜日

[Java]匿名クラスにfinal変数が展開されると

ローカル変数にfinalをつけると、内部で生成している匿名クラスに展開されます。
で、どのように展開されるかというと、匿名クラスのコンストラクターの引数になり、自動生成される同名のメンバ変数に展開されるようです。
とは書いたものの、実際にどうなるかを、classファイルからリバースしてみました。

■変換前のソース
final int hoge1 = 1;
final int hoge2 = 2;
final URL url =new URL("http://localhost/");

btn2.addActionListener(new ActionListener() {
    int hogehoge = 0;
    public void actionPerformed(ActionEvent evt) {
        this.hogehoge = hoge1 + hoge2;
        System.out.print("hogehoge=" + hogehoge);
        System.out.print("hoge1=" + hoge1);

        System.out.print("url=" + url);

        exec();
    }

});


■変換後のソース(一部修正)
/*  51*/        int hoge1 = 1;
/*  52*/        int hoge2 = 2;
/*  53*/        final URL url = new URL("http://localhost/");

/*  55*/        btn2.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent evt)
                    {
/*  58*/                hogehoge = 3;
/*  59*/                System.out.print((new StringBuilder("hogehoge=")).append(hogehoge).toString());
/*  60*/                System.out.print("hoge1=1");

/*  62*/                System.out.print((new StringBuilder("url=")).append(url).toString());

/*  64*/                exec();
                    }
                    int hogehoge;
                    final RefrectionPanel this$0;
                    private final URL val$url;
                    
                    {
/* <-MISALIGNED-> */ /*   1*/                this$0 = RefrectionPanel.this;
/* <-MISALIGNED-> */ /*   1*/                url = url1;
/* <-MISALIGNED-> */ /*  55*/                super();
/* <-MISALIGNED-> */ /*  56*/                hogehoge = 0;
                    }
        }


・・・なんとなく雰囲気はわかるんですが、そのままだとコンパイルエラーです。しかし、コンストラクタでコピー(しようとしている)感じはわかりますね。面白いのは、int型(おそらくプリミティブ)については、値に展開されるところでしょうか。興味深いです。
あ、コレでちょっとしたリバースエンジニアリング対策にもなりますね。

2011年3月8日火曜日

[Java]VMの終了をハンドリングする

たとえばログファイルのクローズなど、システムの終了時に何かをやりたいということが時々あります。
そんなときにに、Runtime#addShutdownHookを使います。引数にはスレッドを渡します。コードはこんな感じ。

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
    public void run() {
        //システム終了時によびだされる
    }
}));