2011年1月30日日曜日

[Java]プライベートフィールドを更新する

UnitTestなどでprivateなフィールドをコードを修正せずに値を設定しようとした場合、publicなアクセッサメソッドを呼び出すか、リフレクションを利用するしかありません。
リフレクションを利用する場合、クラスの型情報を指定する必要がありますが、いちいち指定するのが面倒です。というとで、なかったら再起で呼び出すロジックを組んでみました。コードはこんな感じ。


/**
 * プライベート変数に値を設定します。
 *
 * @param obj インスタンス
 * @param fieldName 変数名
 * @param value 値
 */

public static void setPrivateField(Object obj, String fieldName,Object value) {

    setPrivateField(obj.getClass(), obj, fieldName, value);
}

/**
 * プライベートなstatic変数に値を設定します。
 * finalな変数はダメです。
 *
 * @param cls クラス
 * @param fieldName 変数名
 * @param value 値
 */

public static void setPrivateField(Class<?> cls, String fieldName,
        Object value) {

    setPrivateField(cls, null, fieldName, value);
}

/**
 * プライベートなstatic変数に値を設定します。
 * finalな変数はダメです。
 *
 * @param cls クラス
 * @param obj インスタンス
 * @param fieldName 変数名
 * @param value 値
 */

public static void setPrivateField(Class<?> cls, Object obj, String fieldName, Object value) {

    do {
        try {
            Field field = cls.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
            break;
        } catch (NoSuchFieldException e) {
            // 親クラスからの取得にtry
            cls = cls.getSuperclass();
        } catch (Exception e) {
            // 例外
            e.printStackTrace();
            break;
        }
    } while (cls != null);

}

2011年1月26日水曜日

[Java]プライベートフィールドの値を取得する

privateなフィールドをコードを修正せずに取得しようとした場合、publicなアクセッサメソッドを呼び出すか、リフレクションを利用するしかありません。
リフレクションを利用する場合、クラスの型情報を指定する必要がありますが、いちいち指定するのが面倒です。というとで、なかったら再起で呼び出すロジックを組んでみました。コードはこんな感じ。

/**
 * プライベート変数の値を取得します。
 *
 * @param obj インスタンス
 * @param fieldName 変数名
 * @return 値
 */

public static Object getPrivateField(Object obj, String fieldName) {
    Object result = getPrivateField(obj.getClass(), obj, fieldName);
    return result;
}

/**
 * プライベートなstatic変数の値を取得します。
 *
 * @param cls クラス
 * @param fieldName 変数名
 * @return 値
 */

public static Object getPrivateField(Class<?> cls, String fieldName) {
    Object result = getPrivateField(cls, null, fieldName);
    return result;
}

/**
 * プライベート変数の値を取得します。
 *
 * @param cls クラス
 * @param obj インスタンス
 * @param fieldName 変数名
 * @return 値
 */

public static Object getPrivateField(Class<?> cls, Object obj,
        String fieldName) {
    Object result = null;

    do {
        try {
            Field field = cls.getDeclaredField(fieldName);
            field.setAccessible(true);
            result = field.get(obj);
            break;
        } catch (NoSuchFieldException e) {
            //親クラスからの取得にtry
            cls = cls.getSuperclass();
        } catch (Exception e) {
            //例外
            e.printStackTrace();
            break;
        }
    } while (cls != null);

    return result;
}

2011年1月20日木曜日

[Android]USBドライバ

Android端末をADBで接続する際、USB用のドライバが必要になります。
ということで、コレまで使ったことのあるドライバを備忘のためメモ。


;HTC Desire
%SingleAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C87
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C87&MI_01

;HTC EV4
%SingleAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C8D
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C8D&MI_01

;SHARP IS03
%CompositeAdbInterface% = USB_Install, USB\VID_04DD&PID_939C&MI_05
%CompositeAdbInterface% = USB_Install, USB\VID_04DD&PID_939A&MI_01
%CompositeAdbInterface% = USB_Install, USB\VID_04DD&PID_939B&MI_01

;Xperia X10
%SingleAdbInterface% = USB_Install, USB\VID_0FCE&PID_D12E
%CompositeAdbInterface% = USB_Install, USB\VID_0FCE&PID_D12E&MI_01

;HTC Aria
%SingleAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C92
%CompositeAdbInterface% = USB_Install, USB\VID_0BB4&PID_0C92&MI_01

2011年1月14日金曜日

[Java]プライベートメソッドを呼び出す

UnitTestなどでprivateメソッドをコードを修正せずに実行しようとした場合、該当のprivateメソッドを使っているpublicなメソッドを呼び出すか、リフレクションを利用するしかありません。
リフレクションを利用する場合、クラスの型情報を指定する必要がありますが、いちいち指定するのが面倒です。というとで、なかったら再起で呼び出すロジックを組んでみました。コードはこんな感じ。

/**
 * プライベートメソッド(引数なし)を呼び出します。
 *
 * @param obj インスタンス
 * @param name メソッド名
 * @return 戻り値
 * @throws Throwable プライベートメソッドから発生した例外
 */

public static Object invoke(Object obj, String name) throws Throwable {

    Object result = invoke(obj, new Object[0], name, new Class[0]);
    return result;
}

/**
 * プライベートメソッドを呼び出します。
 *
 * @param obj インスタンス
 * @param args 引数
 * @param name メソッド名
 * @param parameterTypes 引数タイプ
 * @return 戻り値
 * @throws Throwable プライベートメソッドから発生した例外
 */

public static Object invoke(Object obj, Object[] args, String name,
        Class<?>[] parameterTypes) throws Throwable {

    Object result = invoke(obj.getClass(), obj, args, name, parameterTypes);
    return result;
}

/**
 * プライベートメソッドを呼び出します。
 *
 * @param cls クラス
 * @param objインスタンス
 * @param args 引数
 * @param name メソッド名
 * @param parameterTypes 引数タイプ
 * @return 戻り値
 * @throws Throwable プライベートメソッドから発生した例外
 */

public static Object invoke(Class<?> cls, Object obj, Object[] args, String name, Class<?>[] parameterTypes) throws Throwable {

    Object result = null;

    do{
        try {
            Method method = cls.getDeclaredMethod(name, parameterTypes);
            method.setAccessible(true);

            result = method.invoke(obj, args);
            break;

        } catch (NoSuchMethodException e) {
            //親クラスの型でリトライ
            cls = cls.getSuperclass();
        } catch (InvocationTargetException e) {
            throw e.getCause();
        } catch (Throwable e) {
            e.printStackTrace();
            break;
        }
    }while(cls != null);

    return result;
}

2011年1月13日木曜日

[Android]SDKをバージョンアップしたら便利になった!

先日、AndroidのSDKを最新(ver8)にしました。ADTも0.99→8.0にしています。
以下のような変化がありました。

■ライブラリプロジェクトにのプロジェクト名に「-」をつけても大丈夫
 以前はライブラリプロジェクトを参照する側がエラーになっていました。

■ライブラリプロジェクトにnativeライブラリを置いておくと参照側のプロジェクトのapkに反映される
 以前はコピーする必要がありました。

■android.jarへのソース添付が簡単に
 以前は指定ができず、変わったやり方で指定する必要がありましたが、今は他のjarと同じ設定方法でできるようになりました。

■ADTのlogcatビュー
 スタックトレースのダブルクリックでコードにジャンプするようになった。以前はgoto problemをメニュー?から選択する必要があった