短そうな方法でラッパー型とプリミティブ型の相互変換

概要

今日は、ラッパー型のClassオブジェクトとプリミティブ型のClassオブジェクトを相互に変換してみます。

ラッパー→プリミティブ

staticフィールドであるInteger.TYPE はint.classを返します。
他のラッパークラスにも同名のフィールドがあるので、リフレクションでstaticなTYPEフィールドを取り出せばよいとわかります。

プリミティブ→ラッパー

先日のエントリ
変数のデフォルト値(主にプリミティブの)取得の抽象化
の方法でラッパーインスタンスが1つ取得できるので、getClass()をすればラッパー型が取得できます。

ただしこの方法ではvoid.classからVoid.classは取得できません。

コード

package test;

import java.lang.reflect.Array;

public class WrapperToPrimitive {

    @SuppressWarnings("unchecked")
    public static <T> Class<T> wrapperToPrimitive(final Class<T> wrapClass) {
        Class<T> result;
        try {
            result = (Class<T>) wrapClass.getField("TYPE").get(null);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
        if(!result.isPrimitive()) {
            throw new IllegalArgumentException("not wrapper: " + wrapClass);
        }
        return result;
    }
    
    @SuppressWarnings("unchecked")
    public static <T> Class<T> primitiveToWrapper(final Class<T> primClass) {
        return (Class<T>) Array.get(Array.newInstance(primClass, 1), 0).getClass();
    }
    
    public static void main(final String[] args) {
        System.out.println(wrapperToPrimitive(Boolean.class));
        System.out.println(wrapperToPrimitive(Byte.class));
        System.out.println(wrapperToPrimitive(Short.class));
        System.out.println(wrapperToPrimitive(Integer.class));
        System.out.println(wrapperToPrimitive(Long.class));
        System.out.println(wrapperToPrimitive(Float.class));
        System.out.println(wrapperToPrimitive(Double.class));
        System.out.println(wrapperToPrimitive(Character.class));
        System.out.println(wrapperToPrimitive(Void.class));
        
        System.out.println(primitiveToWrapper(boolean.class));
        System.out.println(primitiveToWrapper(byte.class));
        System.out.println(primitiveToWrapper(short.class));
        System.out.println(primitiveToWrapper(int.class));
        System.out.println(primitiveToWrapper(long.class));
        System.out.println(primitiveToWrapper(float.class));
        System.out.println(primitiveToWrapper(double.class));
        System.out.println(primitiveToWrapper(char.class));
//        System.out.println(primitiveToWrapper(void.class));

        
        // 型付き
        Class<Integer> prim = wrapperToPrimitive(Integer.class);
        Class<Integer> wrap = primitiveToWrapper(int.class);
    }

}

実行結果

boolean
byte
short
int
long
float
double
char
void
class java.lang.Boolean
class java.lang.Byte
class java.lang.Short
class java.lang.Integer
class java.lang.Long
class java.lang.Float
class java.lang.Double
class java.lang.Character

ライブラリ

ところで、こういう便利そうなものはすべからくライブラリが用意されています。
当然ですが、本エントリのような遅そうな実装にはなっておらず、条件分岐で実装されていると思います。

http://commons.apache.org/lang/api/org/apache/commons/lang3/ClassUtils.html#wrapperToPrimitive(java.lang.Class)
http://commons.apache.org/lang/api/org/apache/commons/lang3/ClassUtils.html#primitiveToWrapper(java.lang.Class)

ただ、戻り値に型パラメータがついていた方が便利ではないでしょうか。