Java リフレクション が簡単に
javaのリフレクションAPIを簡単に利用できるユーティリティークラスを紹介します。
リフレクションとは
リフレクションAPIは、「java.lang.reflect」パッケージに含まれており、
Javaクラスからフィールドやメソッドなどの情報を取得するAPIです。
主に以下のクラスを使用します。
- java.lang.Class
- java.lang.reflect.Constructor
- java.lang.reflect.Method
- java.lang.reflect.Field
リフレクションを使えば、クラス生成やメソッド呼び出しを直接コーディングすることなく、
文字列からクラスのインスタンスを生成したり、メソッドを実行することができます。
クラス名やメソッド名の定義はXMLなどの外部ファイルへ記述することで、アプリケーションを実行時の環境の変化に動的に対応させることができます。
また、柔軟性の高いアプリケーションを構築するうえで非常に有効なAPIとなっています。
リフレクションの目的
リフレクションはユーザーが直接使うことはあまり多くないのですが、
Struts等のWebアプリケーションやO/Rマッピング等のフレームワーク内では多用されています。
例えば、Web画面の入力データをJavaBeansプロパティに自動設定する場合や、
JavaBeansプロパティを元に自動的に更新するSQLを発行する場合などに利用されています。
また、アプリケーションの起動時に機能を拡張するプラグインを動的に読み込んで登録するといった機能はリフレクションを使うと簡単に実現できます。
サンプルの実行
では、サンプルを実行して頂き、是非フレームワーク的なプログラミングを体感してください。
ここでは以下のクラスを使用しリフレクションユーティリティの簡単な使い方を示しています。
Main.java・・・実行するクラス
BeanUtil.java・・・リフレクションのユーティリティクラス
FreeSoft.java・・・フリーソフを表すクラスでリフレクションとして利用されます。
●通常通り実行した場合
FreeSoft freeSoft = new FreeSoft();
freeSoft.setName(“Chat&Messenger チャットもメッセンジャーも!!”);
freeSoft.showName();
freeSoft.showPrice(0);
●リフレクションを使用して実行した場合
// FreeSoftクラスのインスタンス生成
Object invokeObject = BeanUtil.newInstance(“FreeSoft”);
// nameフィールドに値をセットする。
BeanUtil.setProperty(invokeObject, “name” , “Chat&Messenger チャットもメッセンジャーも!!”);
// FreeSoftのshowName()メソッドを実行します。
BeanUtil.invoke(invokeObject, “showName”, null);
// FreeSoftのshowPrice()メソッドを実行します。
// メソッドに引数がある場合はObject型の配列で渡す必要がある。
BeanUtil.invoke(invokeObject, “showPrice”,new Object[]{new Integer(0)});
●実行結果
通常の場合も、リフレクションを使用した場合も実行結果は同じですね。
ソフト名:Chat&Messenger チャットもメッセンジャーも!!
価格 :0円
>>>リフレクションを使用した場合
ソフト名:Chat&Messenger チャットもメッセンジャーも!!
価格 :0円
BeanUtilメソッド詳細
newInstance
public static Object newInstance(String className) throws Exception
- 文字列「className」からインスタンスを生成し返します。
-
- パラメータ:
className
– 完全修飾クラス名- 戻り値:
- 完全修飾クラス名の新しいインスタンス
- 例外:
Exception
newInstance
public static Object newInstance(String className, Object[] argObj) throws Exception
- 文字列「className」からインスタンスを生成し返します。
-
- パラメータ:
className
– 完全修飾クラス名argObj
– コンストラクタの引数- 戻り値:
- 完全修飾クラス名の新しいインスタンス
- 例外:
Exception
newInstance
public static Object newInstance(Class clazz) throws Exception
- クラス「clazz」からインスタンスを生成し返します。
-
- パラメータ:
clazz
– クラス- 戻り値:
- clazzの新しいインスタンス
- 例外:
Exception
newInstance
public static Object newInstance(Class clazz, Object[] argObj) throws Exception
- クラス「clazz」からインスタンスを生成し返します。
-
- パラメータ:
clazz
– クラスargObj
– コンストラクタの引数- 戻り値:
- clazzの新しいインスタンス
- 例外:
Exception
setProperty
public static void setProperty(Object invokeObject, String fieldName, Object value) throws Exception
- オブジェクト「invokeObject」のフィールド「fieldName」のsetterメソッドを 呼び出し、値「value」を格納します。
setterメソッドがなければフィールドへダイレクトに値を設定します。 ただし、この場合対象プロパティのアクセス修飾子はpublicであること
-
- パラメータ:
invokeObject
– 実行対象のオブジェクトfieldName
– 実行対象のオブジェクトのプロパティ名value
– セットする値- 例外:
Exception
– 以下の例外が発生します。InvocationTargetException
– 基本となるメソッドが例外をスローする場合IllegalAccessException
– この Method オブジェクトが Java
言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合NoSuchMethodException
– 指定された名前のメソッドが見つからない場合
getProperty
public static Object getProperty(Object invokeObject, String fieldName) throws Exception
- オブジェクト invokeObject のフィールド fieldName のgetterメソッドを 呼び出し値を取得します。
getterメソッドがなければフィールドからダイレクトに値を取得します。 ただし、この場合対象プロパティのアクセス修飾子はpublicであること -
- パラメータ:
invokeObject
– 実行対象のオブジェクトfieldName
– 実行対象のオブジェクトのプロパティ名- 戻り値:
- ゲッターメソッドのリターン値
- 例外:
Exception
– 以下の例外が発生します。InvocationTargetException
– 基本となるメソッドが例外をスローする場合IllegalAccessException
– この Method オブジェクトが Java
言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合NoSuchFieldException
– 指定された名前のフィールドが見つからない場合
invoke
public static Object invoke(Object invokeObject, String callMethod, Object[] argObjects) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException
- オブジェクト「invokeObject」のメソッド「callMethod」を実行します。
リターン値がある場合は、Object形として得る事ができます。 -
- パラメータ:
invokeObject
– 実行対象のオブジェクトcallMethod
– 実行対象のメソッド名argObjects
– 引数がある場合はオブジェクトの配列として渡す。 引数が無い場合はnullを渡します。- 戻り値:
- 「callMethod」を実行したリターン値
- 例外:
InvocationTargetException
– 基本となるメソッドが例外をスローする場合IllegalAccessException
– この Method オブジェクトが Java
言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合NoSuchMethodException
– 指定された名前のメソッドが見つからない場合
findMethod
public static Method findMethod(Object invokeObject, String callMethod, Object[] argObjects) throws NoSuchMethodException
- オブジェクト「invokeObject」のメソッド「callMethod」を検索します。
-
- パラメータ:
invokeObject
– 実行対象のオブジェクトcallMethod
– 実行対象のオブジェクトのメソッド名argObjects
– 引数がある場合はオブジェクトの配列として渡す。 引数が無い場合はnullを渡します。- 戻り値:
- 指定された引数の条件に一致するMethod オブジェクト
- 例外:
NoSuchMethodException
– 一致するメソッドが見つからない場合、 あるいは名前が “” または “”の場合
setField
public static void setField(Object invokeObject, String fieldName, Object value) throws IllegalAccessException, NoSuchFieldException
- 実行対象のオブジェクト「invokeObject」のフィールド名「fieldName」に値 「value 」を格納します。
-
- パラメータ:
invokeObject
– 実行対象のオブジェクトfieldName
– 実行対象のオブジェクトのフィールド名value
– セットする値- 例外:
IllegalAccessException
– 指定されたオブジェクトが基本と なるフィールド (またはそのサブクラスか実装側)
を宣言する クラスまたはインタフェースのインスタンスではない場合、 ある いはラップ解除変換が失敗した場合NoSuchFieldException
– 指定された名前のフィールドが見つからない場合
getField
public static Object getField(Object invokeObject, String fieldName) throws IllegalAccessException, NoSuchFieldException
- 実行対象のオブジェクト「invokeObject」のフィールド名「fieldName」の値を 取得します。
-
- パラメータ:
invokeObject
– 実行対象のオブジェクトfieldName
– 実行対象のオブジェクトのフィールド名- 戻り値:
- リターン値
- 例外:
IllegalAccessException
– 指定されたオブジェクトが基本と なるフィールド (またはそのサブクラスか実装側)
を宣言する クラスまたはインタフェースのインスタンスではない場合、 ある いはラップ解除変換が失敗した場合NoSuchFieldException
– 指定された名前のフィールドが見つからない場合
hasField
public static boolean hasField(Object object, String fieldName) throws Exception
- オブジェクト「object」がフィールド名「fieldName」を 宣言しているかどうかを 確認します。
-
- パラメータ:
object
– 検査対象のオブジェクトfieldName
– 検査するフィールド名- 戻り値:
- 宣言している場合true
- 例外:
Exception
getAllFields
public static java.util.TreeSet getAllFields(Object object) throws Exception
-
- パラメータ:
object
–- 戻り値:
- 例外:
Exception
getShortClassName
public static String getShortClassName(Object object)
- オブジェクトから完全修飾していないクラス名を取得します。
-
- パラメータ:
object
–- 戻り値:
getShortClassName
public static String getShortClassName(String className)
- 完全修飾名からクラス名を取得します。
-
- パラメータ:
className
–- 戻り値:
getFieldName
public static String getFieldName(String methodName)
- メソッド名からフィールド名を変えします。 JavaBeansの慣例に適合している 必要があります。
-
- パラメータ:
methodName
–- 戻り値:
isClassExist
public static boolean isClassExist(String className)
- 完全修飾名「className」が存在するクラス名かを検証します。
-
- パラメータ:
className
–- 戻り値:
getPropertyDescriptors
public static PropertyDescriptor[] getPropertyDescriptors(Object object) throws IntrospectionException
- 「object」のオブジェクト情報を保持するPropertyDescriptorを返します。
-
- パラメータ:
object
–- 戻り値:
- 例外:
java.beans.IntrospectionException
BeanUtilソースコード
/**
* javaのリフレクションAPIを簡単に利用できるユーティリティークラス
*/
public class BeanUtil {
/** */
private static final String GET = “GET”;
/** */
private static final String SET = “SET”;
// ———————————————————-『 newInstance 』
/**
* 文字列「className」からインスタンスを生成し返します。
* @param className 完全修飾クラス名
* @return 完全修飾クラス名の新しいインスタンス
* @throws Exception
*/
public static Object newInstance(String className) throws Exception {
try {
return Class.forName(className).newInstance();
} catch (NoClassDefFoundError e) {
System.err.println(“NoClassDefFoundError : ” + className);
throw e;
}
}
/**
* 文字列「className」からインスタンスを生成し返します。
* @param className 完全修飾クラス名
* @param argObj コンストラクタの引数
* @return 完全修飾クラス名の新しいインスタンス
* @throws Exception
*/
public static Object newInstance(String className, Object[] argObj)
throws Exception {
Class[] argClass = new Class[argObj.length];
for (int i = 0; i < argObj.length; i++) {
argClass[i] = argObj[i].getClass();
}
Constructor c = Class.forName(className).getConstructor(argClass);
return c.newInstance(argObj);
}
/**
* クラス「clazz」からインスタンスを生成し返します。
* @param clazz クラス
* @return clazzの新しいインスタンス
* @throws Exception
*/
public static Object newInstance(Class clazz) throws Exception {
return clazz.newInstance();
}
/**
* クラス「clazz」からインスタンスを生成し返します。
* @param clazz クラス
* @param argObj コンストラクタの引数
* @return clazzの新しいインスタンス
* @throws Exception
*/
public static Object newInstance(Class clazz, Object[] argObj)
throws Exception {
Class[] argClass = new Class[argObj.length];
for (int i = 0; i < argObj.length; i++) {
argClass[i] = argObj[i].getClass();
}
Constructor c = clazz.getConstructor(argClass);
return c.newInstance(argObj);
}
// —————————————————————『 Method 』
/**
* オブジェクト「invokeObject」のフィールド「fieldName」のsetterメソッドを
* 呼び出し、値「value」を格納します。
* <br>
* setterメソッドがなければフィールドへダイレクトに値を設定します。
* ただし、この場合対象プロパティのアクセス修飾子はpublicであること
* @param invokeObject 実行対象のオブジェクト
* @param fieldName 実行対象のオブジェクトのプロパティ名
* @param value セットする値
* @throws Exception 以下の例外が発生します。
* @throws InvocationTargetException 基本となるメソッドが例外をスローする場合
* @throws IllegalAccessException この Method オブジェクトが Java
* 言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合
* @throws NoSuchMethodException 指定された名前のメソッドが見つからない場合
*/
public static void setProperty(Object invokeObject, String fieldName,
Object value) throws Exception {
try {
Method method = searchMethod(invokeObject, fieldName, SET);
Class[] paramClasses = method.getParameterTypes();
Object[] valueArray = null;
if (paramClasses[0].isInstance(value)) {
// セットするオブジェクトが引数のクラスのサブクラスなら変換しない。
valueArray = new Object[] { value };
} else {
valueArray = new Object[] { convObject(value, paramClasses[0]
.getName()) };
}
method.invoke(invokeObject, valueArray);
} catch (NoSuchMethodException e) {
try {
// setterメソッドがなければフィールドにダイレクトにセットする。
setField(invokeObject, fieldName, value);
} catch (NoSuchFieldException fe) {
String errorMes = “\nクラス” + getShortClassName(invokeObject)
+ “は、” + “フィールド「” + fieldName + “」に対し\n”
+ “アクセス可能なセッターメソッドがなく、かつ。”
+ “フィールド「” + fieldName
+ “」もpublicではありません。” + “”;
throw new IllegalAccessException(errorMes);
}
}
}
/**
* オブジェクト invokeObject のフィールド fieldName のgetterメソッドを
* 呼び出し値を取得します。 <br>
* getterメソッドがなければフィールドからダイレクトに値を取得します。
* ただし、この場合対象プロパティのアクセス修飾子はpublicであること
* @param invokeObject 実行対象のオブジェクト
* @param fieldName 実行対象のオブジェクトのプロパティ名
* @return ゲッターメソッドのリターン値
* @throws Exception 以下の例外が発生します。
* @throws InvocationTargetException 基本となるメソッドが例外をスローする場合
* @throws IllegalAccessException この Method オブジェクトが Java
* 言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合
* @throws NoSuchFieldException 指定された名前のフィールドが見つからない場合
*/
public static Object getProperty(Object invokeObject, String fieldName)
throws Exception {
try {
Method method = searchMethod(invokeObject, fieldName, GET);
return method.invoke(invokeObject, null);
} catch (NoSuchMethodException e) {
return getField(invokeObject, fieldName);
}
}
/**
* オブジェクト「invokeObject」のメソッド「callMethod」を実行します。
* リターン値がある場合は、Object形として得る事ができます。
* @param invokeObject 実行対象のオブジェクト
* @param callMethod 実行対象のメソッド名
* @param argObjects 引数がある場合はオブジェクトの配列として渡す。
* 引数が無い場合はnullを渡します。
* @return 「callMethod」を実行したリターン値
* @throws InvocationTargetException 基本となるメソッドが例外をスローする場合
* @throws IllegalAccessException この Method オブジェクトが Java
* 言語アクセス制御を実施し、基本となるメソッドにアクセスでき ない場合
* @throws NoSuchMethodException 指定された名前のメソッドが見つからない場合
*/
public static Object invoke(Object invokeObject, String callMethod,
Object[] argObjects) throws InvocationTargetException,
IllegalAccessException, NoSuchMethodException {
Method method = findMethod(invokeObject, callMethod, argObjects);
return method.invoke(invokeObject, argObjects);
}
/**
* オブジェクト「invokeObject」のメソッド「callMethod」を検索します。
* @param invokeObject 実行対象のオブジェクト
* @param callMethod 実行対象のオブジェクトのメソッド名
* @param argObjects 引数がある場合はオブジェクトの配列として渡す。
* 引数が無い場合はnullを渡します。
* @return 指定された引数の条件に一致するMethod オブジェクト
* @throws NoSuchMethodException 一致するメソッドが見つからない場合、
* あるいは名前が “<init>” または “<clinit>”の場合
*/
public static Method findMethod(Object invokeObject, String callMethod,
Object[] argObjects) throws NoSuchMethodException {
Class[] paramClasses = null;
Method[] methods = invokeObject.getClass().getMethods();
top: for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().equals(callMethod)) {
if (argObjects == null
&& methods[i].getParameterTypes().length == 0) {
return methods[i];
}
if (argObjects == null) {
continue;
}
paramClasses = methods[i].getParameterTypes();
if (paramClasses.length == argObjects.length) {
// 全てのパラメーターリストの型と、引数の型の検証
for (int j = 0; j < paramClasses.length; j++) {
Class paramClass = paramClasses[j];
Object argObj = argObjects[j];
// 引数の型がプリミティブの場合、引数のオブジェクト
// がnullでなくプリミティブ
// もしくわ、NumberのサブクラスならOKとする。
if (argObj == null) {
continue;
}
if (paramClass.isPrimitive()
&& (argObj instanceof Number || argObj
.getClass().isPrimitive())) {
continue;
}
if (!paramClass.isInstance(argObj)) {
// 型に暗黙変換の互換性が無い時点で、次のメソッドへ
continue top;
}
}
return methods[i];
}
}
}
String paramLength = (paramClasses != null) ? Integer
.toString(paramClasses.length) : “”;
String errorMes = getShortClassName(invokeObject) + “にメソッド”
+ callMethod + “はありません。” + “[ paramClasses.length ] = ”
+ paramLength + “,[ argObjects.length ] = ” + argObjects.length
+ “”;
throw new NoSuchMethodException(errorMes);
}
// —————————————————————-『 Field 』
/**
* 実行対象のオブジェクト「invokeObject」のフィールド名「fieldName」に値
* 「value 」を格納します。
* @param invokeObject 実行対象のオブジェクト
* @param fieldName 実行対象のオブジェクトのフィールド名
* @param value セットする値
* @throws IllegalAccessException 指定されたオブジェクトが基本と
* なるフィールド (またはそのサブクラスか実装側)
* を宣言する クラスまたはインタフェースのインスタンスではない場合、
* ある いはラップ解除変換が失敗した場合
* @throws NoSuchFieldException 指定された名前のフィールドが見つからない場合
*/
public static void setField(Object invokeObject, String fieldName,
Object value) throws IllegalAccessException, NoSuchFieldException {
Field field = searchField(invokeObject, fieldName);
String className = field.getType().getName();
Object convObj = null;
if (field.getType().isInstance(value)) {
convObj = value;
} else {
convObj = convObject(value, className);
}
field.set(invokeObject, convObj);
}
/**
* 実行対象のオブジェクト「invokeObject」のフィールド名「fieldName」の値を
* 取得します。
* @param invokeObject 実行対象のオブジェクト
* @param fieldName 実行対象のオブジェクトのフィールド名
* @return リターン値
* @throws IllegalAccessException 指定されたオブジェクトが基本と
* なるフィールド (またはそのサブクラスか実装側)
* を宣言する クラスまたはインタフェースのインスタンスではない場合、
* ある いはラップ解除変換が失敗した場合
* @throws NoSuchFieldException 指定された名前のフィールドが見つからない場合
*/
public static Object getField(Object invokeObject, String fieldName)
throws IllegalAccessException, NoSuchFieldException {
Field field = searchField(invokeObject, fieldName);
return field.get(invokeObject);
}
/**
* オブジェクト「object」がフィールド名「fieldName」を 宣言しているかどうかを
* 確認します。
* @param object 検査対象のオブジェクト
* @param fieldName 検査するフィールド名
* @return 宣言している場合true
* @throws Exception
*/
public static boolean hasField(Object object, String fieldName)
throws Exception {
PropertyDescriptor[] props = getPropertyDescriptors(object);
for (int i = 0; i < props.length; i++) {
String _fieldName = props[i].getName();
if (fieldName.equals(_fieldName)) {
return true;
}
}
return false;
}
/**
*
* @param object
* @return
* @throws Exception
*/
public static TreeSet getAllFields(Object object) throws Exception {
TreeSet fieldSet = new TreeSet();
// メソッドからプロパ-ティ名の取得
PropertyDescriptor[] props = getPropertyDescriptors(object);
for (int i = 0; i < props.length; i++) {
String fieldName = props[i].getName();
fieldSet.add(fieldName);
}
// フィールドからプロパ-ティ名の取得
Field[] fields = object.getClass().getFields();
for (int i = 0; i < fields.length; i++) {
String fieldName = fields[i].getName();
if (!fieldSet.contains(fieldName)) {
fieldSet.add(fieldName);
}
}
return fieldSet;
}
/**
*
* @param invokeObject 実行対象のオブジェクト
* @param fieldName 実行対象のオブジェクトのフィールド名
* @return 指定された引数の条件に一致する Filed オブジェクト
* @throws NoSuchFieldException 指定された名前のフィールドが見つからない場合
*/
private static Field searchField(Object invokeObject, String fieldName)
throws NoSuchFieldException {
try {
return invokeObject.getClass().getField(fieldName);
} catch (NoSuchFieldException e) {
// このスコープはテーブルカラム名からの取得
fieldName = checkFieldName(fieldName);
Field[] fields = invokeObject.getClass().getFields();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName().equalsIgnoreCase(fieldName)) {
return fields[i];
}
}
throw new NoSuchFieldException(fieldName);
}
}
// —————————————————————-『 その他 』
/**
* オブジェクトから完全修飾していないクラス名を取得します。
* @param object
* @return
*/
public static String getShortClassName(Object object) {
if (object == null) {
return “null”;
}
String name = object.getClass().getName();
return getShortClassName(name);
}
/**
* 完全修飾名からクラス名を取得します。
* @param className
* @return
*/
public static String getShortClassName(String className) {
int index = className.lastIndexOf(“.”);
return className.substring(index + 1);
}
/**
* メソッド名からフィールド名を変えします。 JavaBeansの慣例に適合している
* 必要があります。
* @param methodName
* @return
*/
public static String getFieldName(String methodName) {
String fieldName = null;
if (methodName.startsWith(“is”)) {
fieldName = methodName.substring(2);
} else {
fieldName = methodName.substring(3);
}
fieldName = convString(fieldName, 0, “L”);
return fieldName;
}
/**
* 完全修飾名「className」が存在するクラス名かを検証します。
* @param className
* @return
*/
public static boolean isClassExist(String className) {
try {
Class.forName(className);
return true;
} catch (Exception e) {
return false;
}
}
private final static Map beanInfoCache = new HashMap();
/**
* 「object」のオブジェクト情報を保持するPropertyDescriptorを返します。
* @param object
* @return
* @throws IntrospectionException
*/
public static PropertyDescriptor[] getPropertyDescriptors(Object object)
throws IntrospectionException {
BeanInfo beanInfo = (BeanInfo) beanInfoCache.get(object.getClass());
if (beanInfo == null) {
beanInfo = Introspector.getBeanInfo(object.getClass());
beanInfoCache.put(object.getClass(), beanInfo);
}
// BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
return beanInfo.getPropertyDescriptors();
}
// ————————————————————————–
// ———————————————『 以下プライベートメソッド 』
// ————————————————————————–
/**
* PropertyDescriptorを元に、引数のfieldNameのアクセサメッソドを サーチします。
* @param invokeObject 実行対象のオブジェクト
* @param fieldName フィールド名
* @param type ゲッターメソッド ⇒ GET ゲッターメソッド ⇒ SET
* @return 指定された引数の条件に一致するMethod オブジェクト
* @throws NoSuchMethodException 一致するメソッドが見つからない場合、
* あるいは名前が “<init>” または “<clinit>”
* の場合
* @throws IntrospectionException
*/
private static Method searchMethod(Object invokeObject, String fieldName,
String type) throws NoSuchMethodException, IntrospectionException {
Method method = null;
fieldName = checkFieldName(fieldName);
PropertyDescriptor[] props = getPropertyDescriptors(invokeObject);
for (int i = 0; i < props.length; i++) {
String name = props[i].getName();
if (!name.equalsIgnoreCase(fieldName)) {
continue;
}
if (type.equals(GET)) {
method = props[i].getReadMethod();
} else {
method = props[i].getWriteMethod();
}
if (method == null) {
continue;
}
return method;
}
// メソッドが存在しない場合。
throw new NoSuchMethodException(“クラスにメソッドがありません。”
+ “(大文字小文字の区別なしです。): ” + type.toLowerCase()
+ convString(fieldName, 0, “U”) + “()”);
}
/**
* 引数のfieldNameがカラム名の場合をチェックし、カラム名の場合は
* コンバートし返します。
*
* MAIL_ADDRESS ⇒ MAILADDRESS ↓ mailaddress = mailAddress
* @param fieldName フィールド名または、カラム名
* @return フィールド名
*/
private static String checkFieldName(String fieldName) {
int index = fieldName.indexOf(“_”);
while (true) {
if (index == -1) {
return fieldName;
}
StringBuffer convcloumn = new StringBuffer(fieldName);
convcloumn.deleteCharAt(index);
fieldName = convcloumn.toString();
index = fieldName.indexOf(“_”);
}
}
/**
* 変換対象のオブジェクト object を convClassName の型へ変換します。
*
* @param object 変換対象のオブジェクト
* @param convClassName 変換する型のクラス文字列
* @return 変換されたオブジェクト
*/
private static Object convObject(Object object, String convClassName) {
if (object == null) {
// プリミティブな型への変換はnullで返すとエラーになる。
// 0のラッパーにする。
if (convClassName.equals(“int”)) {
return new Integer(0);
} else if (convClassName.equals(“long”)) {
return new Long(0);
} else {
return null;
}
}
if (object.getClass().getName().equals(convClassName)) {
return object;
}
// —————————————-『 object instanceof String 』
if (object instanceof String) {
if (convClassName.equals(“java.lang.String”)) {
return object;
} else if (convClassName.equals(“java.lang.Long”)
|| convClassName.equals(“long”)) {
String str = (String) object;
if (isExist(str)) {
// 一度BigDecimalに変換しないと具合が悪い
// 1000.00000
BigDecimal big = new BigDecimal(str);
return new Long(big.longValue());
} else {
// str が殻リテラルの場合は初期値の”0″を
return new Long(0);
}
} else if (convClassName.equals(“java.sql.Date”)) {
return toSqlDate((String) object);
} else if (convClassName.equals(“java.sql.Timestamp”)) {
Date date = toSqlDate((String) object);
return new Timestamp(date.getTime());
} else if (convClassName.equals(“java.lang.Integer”)
|| convClassName.equals(“int”)) {
// str が殻リテラルの場合は初期値の”0″を
String str = (String) object;
if (isExist(str)) {
BigDecimal big = new BigDecimal(str);
return new Integer(big.intValue());
} else {
return new Integer(0);
}
} else if (convClassName.equals(“boolean”)) {
return Boolean.valueOf(object.toString());
} else if (convClassName.equals(“java.math.BigDecimal”)) {
String temp = ((String) object).trim();
// temp.length() == 0の場合0ではなくnullにするのが無難。
if (temp.length() == 0) {
return null;
} else {
return new BigDecimal(temp);
}
}
throwNoSupprt(object, convClassName);
}
// ———————————『 object instanceof java.sql.Date 』
else if (object instanceof java.sql.Date) {
if (convClassName.equals(“java.lang.String”)) {
return toStringDate((java.sql.Date) object, “yyyy/MM/dd”);
} else if (convClassName.equals(“java.sql.Date”)) {
return object;
} else if (convClassName.equals(“java.sql.Timestamp”)) {
return new Timestamp(((Date) object).getTime());
}
throwNoSupprt(object, convClassName);
}
// ————————————-『 object instanceof Timestamp 』
else if (object instanceof Timestamp) {
long time = ((Timestamp) object).getTime();
if (convClassName.equals(“java.lang.String”)) {
return toStringDate(time, “yyyy/MM/dd HH:mm:ss”);
} else if (convClassName.equals(“java.sql.Date”)) {
return new java.sql.Date(time);
} else if (convClassName.equals(“java.sql.Timestamp”)) {
return object;
}
throwNoSupprt(object, convClassName);
}
// —————————————-『 object instanceof Integer 』
else if (object instanceof Integer) {
if (convClassName.equals(“java.lang.Integer”)
|| convClassName.equals(“int”)) {
return object;
} else if (convClassName.equals(“java.lang.String”)) {
return object.toString();
} else if (convClassName.equals(“java.lang.Long”)
|| convClassName.equals(“long”)) {
return new Long(((Integer) object).longValue());
} else if (convClassName.equals(“java.math.BigDecimal”)) {
return new BigDecimal(((Integer) object).intValue());
}
throwNoSupprt(object, convClassName);
}
// ——————————————『 object instanceof Long 』
else if (object instanceof Long) {
if (convClassName.equals(“java.lang.Long”)
|| convClassName.equals(“long”)) {
return object;
} else if (convClassName.equals(“java.lang.String”)) {
return object.toString();
} else if (convClassName.equals(“java.lang.Integer”)
|| convClassName.equals(“int”)) {
return new Integer(((Long) object).intValue());
} else if (convClassName.equals(“java.math.BigDecimal”)) {
return new BigDecimal(((Long) object).longValue());
}
throwNoSupprt(object, convClassName);
}
// —————————————-『 object instanceof Double 』
else if (object instanceof Double) {
if (convClassName.equals(“java.lang.String”)) {
// COLUMN NUMBER(8,0)
// windows oracle > BigDecimal
// UNIX oracle > Double
BigDecimal big = new BigDecimal(((Double) object).doubleValue());
int scale = big.scale();
if (scale == 0) {
return big.toString();
} else {
// 丸めが必要な場合はサポートしない。
throwNoSupprt(object, convClassName);
}
}
if (convClassName.equals(“java.lang.Integer”)
|| convClassName.equals(“int”)) {
return new Integer(((Double) object).intValue());
} else if (convClassName.equals(“java.lang.Long”)
|| convClassName.equals(“long”)) {
return new Long(((Double) object).longValue());
} else if (convClassName.equals(“java.math.BigDecimal”)) {
return new BigDecimal(((Double) object).doubleValue());
}
throwNoSupprt(object, convClassName);
}
// ————————————『 object instanceof BigDecimal 』
else if (object instanceof BigDecimal) {
if (convClassName.equals(“java.lang.String”)) {
return object.toString();
} else if (convClassName.equals(“java.lang.Long”)
|| convClassName.equals(“long”)) {
return new Long(((BigDecimal) object).longValue());
} else if (convClassName.equals(“java.lang.Integer”)
|| convClassName.equals(“int”)) {
return new Integer(((BigDecimal) object).intValue());
}
throwNoSupprt(object, convClassName);
}
// —————————————-『 object instanceof byte[] 』
else if (object instanceof byte[]) {
if (convClassName.equals(“java.sql.Blob”)) {
return object;
}
throwNoSupprt(object, convClassName);
}
// ————————————————『 object が Boolean 』
else if (object instanceof Boolean) {
if (convClassName.equals(“boolean”)) {
return object;
}
throwNoSupprt(object, convClassName);
}
// ———————————————-『 object が boolean[] 』
else if (object instanceof boolean[]) {
if (convClassName.equals(“java.lang.String”)) {
boolean[] bs = (boolean[]) object;
StringBuffer buff = new StringBuffer(“[“);
for (int i = 0; i < bs.length; i++) {
buff.append(bs[i] + “,”);
}
buff.deleteCharAt(buff.length() – 1);
buff.append(“]”);
return buff.toString();
}
throwNoSupprt(object, convClassName);
}
throwNoSupprt(object, convClassName);
return null;
}
/**
* 変換がサポートされていない場合にスローします。
*
* @param object 変換対象のオブジェクト
* @param convClassName 変換する型
*/
private static void throwNoSupprt(Object object, String convClassName) {
String className = (object != null) ? object.getClass().getName()
: “null”;
String errorMess = “\nこのObjectの型変換処理はまだサポートされていません。\n”
+ ” [ Object ] = ” + object + “,[ Objectの型 ] = ” + className
+ “,[ convertClass ] = ” + convClassName + “”;
throw new UnsupportedOperationException(errorMess);
}
/**
* 文字列[str]に対して[index]の位置にある文字を大文字または小文字に変換します。
* <p>
* @param str 評価対象の文字列
* @param index 指定する位置
* @param toCase 大文字に変換 ⇒ U | u 小文字に変換 ⇒ L | l
* @return 変換後の文字列
*/
private static String convString(String str, int index, String toCase) {
if (str == null || str.trim().length() == 0) {
return str;
} else {
String temp = str.substring(index, index + 1);
if (toCase.equalsIgnoreCase(“u”)) {
temp = temp.toUpperCase();
} else {
temp = temp.toLowerCase();
}
StringBuffer tempBuffer = new StringBuffer(str);
tempBuffer.replace(index, index + 1, temp);
return tempBuffer.toString();
}
}
/**
* [value]が有効な値かどうか検証します。
*
* @param value 評価対象文字列
* @return [true]:nullでなく””でない場合
*/
private static boolean isExist(String value) {
if (value != null && value.length() != 0) {
return true;
}
return false;
}
/**
* java.util.Dateクラスまたは、そのサブクラスを指定のフォーマットで
* 文字列に変換します。
* @param date 変換対象のjava.util.Dateクラス
* @param pattern 指定のフォーマット
* @return フォーマットされた日付文字列
*/
private static String toStringDate(Date date, String pattern) {
SimpleDateFormat sdFormat = new SimpleDateFormat(pattern);
return sdFormat.format(date);
}
private static java.sql.Date toSqlDate(String strDate) {
Calendar cal = toCalendar(strDate);
return toSqlDate(cal);
}
private static java.sql.Date toSqlDate(Calendar cal) {
long l = cal.getTime().getTime();
return new java.sql.Date(l);
}
/**
* 時間のロング値を指定のフォーマットで文字列に変換します。
* @param time 現在時刻のミリ秒を表すロング値
* @param pattern 指定のフォーマット
* @return フォーマットされた日付文字列
*/
private static String toStringDate(long time, String pattern) {
return toStringDate(new Date(time), pattern);
}
/**
* String ⇒ java.sql.Date
*
* 以下の日付文字列をjava.sql.Dateに変換
* yyyy/MM/dd HH:mm:ss.SSS yyyy-MM-dd HH:mm:ss.SSS
*
* “20030407” “2003/04/07” “2003-04-07” “2003/04/07 15:20:16” “2003-04-07
* 15:20:16”
* @param strDate
* @return
*/
private static Calendar toCalendar(String strDate) {
strDate = format(strDate);
Calendar cal = Calendar.getInstance();
int yyyy = Integer.parseInt(strDate.substring(0, 4));
int MM = Integer.parseInt(strDate.substring(5, 7));
int dd = Integer.parseInt(strDate.substring(8, 10));
int HH = cal.get(Calendar.HOUR_OF_DAY);
int mm = cal.get(Calendar.MINUTE);
int ss = cal.get(Calendar.SECOND);
int SSS = cal.get(Calendar.MILLISECOND);
cal.clear();
cal.set(yyyy, MM – 1, dd);
int len = strDate.length();
switch (len) {
case 10:
break;
case 16: // yyyy/MM/dd HH:mm
HH = Integer.parseInt(strDate.substring(11, 13));
mm = Integer.parseInt(strDate.substring(14, 16));
cal.set(Calendar.HOUR_OF_DAY, HH);
cal.set(Calendar.MINUTE, mm);
break;
case 19: // yyyy/MM/dd HH:mm:ss
HH = Integer.parseInt(strDate.substring(11, 13));
mm = Integer.parseInt(strDate.substring(14, 16));
ss = Integer.parseInt(strDate.substring(17, 19));
cal.set(Calendar.HOUR_OF_DAY, HH);
cal.set(Calendar.MINUTE, mm);
cal.set(Calendar.SECOND, ss);
break;
case 23: // yyyy/MM/dd HH:mm:ss.SSS
HH = Integer.parseInt(strDate.substring(11, 13));
mm = Integer.parseInt(strDate.substring(14, 16));
ss = Integer.parseInt(strDate.substring(17, 19));
SSS = Integer.parseInt(strDate.substring(20, 23));
cal.set(Calendar.HOUR_OF_DAY, HH);
cal.set(Calendar.MINUTE, mm);
cal.set(Calendar.SECOND, ss);
cal.set(Calendar.MILLISECOND, SSS);
break;
default:
throw new IllegalStateException(
“このString文字列は日付文字列に変換できません : ”
+ strDate);
}
return cal;
}
/**
* あらゆる日付文字列を”yyyy/MM/dd” or “yyyy/MM/dd HH:mm:ss”の
* フォーマットに変換することを試みます。
* 例:03/1/3 ⇒ 2003/01/03
* @param strDate
* @return
*/
private static String format(String strDate) {
strDate = strDate.trim();
String yyyy = null;
String MM = null;
String dd = null;
String HH = null;
String mm = null;
String ss = null;
String SSS = null;
// “-” or “/” が無い場合
if (strDate.indexOf(“/”) == -1 && strDate.indexOf(“-“) == -1) {
if (strDate.length() == 8) {
yyyy = strDate.substring(0, 4);
MM = strDate.substring(4, 6);
dd = strDate.substring(6, 8);
return yyyy + “/” + MM + “/” + dd;
} else {
yyyy = strDate.substring(0, 4);
MM = strDate.substring(4, 6);
dd = strDate.substring(6, 8);
HH = strDate.substring(9, 11);
mm = strDate.substring(12, 14);
ss = strDate.substring(15, 17);
return yyyy + “/” + MM + “/” + dd + ” ” + HH + “:” + mm + “:”
+ ss;
}
}
StringTokenizer token = new StringTokenizer(strDate, “_/-:. “);
StringBuffer result = new StringBuffer();
for (int i = 0; token.hasMoreTokens(); i++) {
String temp = token.nextToken();
switch (i) {
case 0:// 年の部分
yyyy = fillString(strDate, temp, “f”, “20”, 4);
result.append(yyyy);
break;
case 1:// 月の部分
MM = fillString(strDate, temp, “f”, “0”, 2);
result.append(“/” + MM);
break;
case 2:// 日の部分
dd = fillString(strDate, temp, “f”, “0”, 2);
result.append(“/” + dd);
break;
case 3:// 時間の部分
HH = fillString(strDate, temp, “f”, “0”, 2);
result.append(” ” + HH);
break;
case 4:// 分の部分
mm = fillString(strDate, temp, “f”, “0”, 2);
result.append(“:” + mm);
break;
case 5:// 秒の部分
ss = fillString(strDate, temp, “f”, “0”, 2);
result.append(“:” + ss);
break;
case 6:// ミリ秒の部分
SSS = fillString(strDate, temp, “b”, “0”, 3);
result.append(“.” + SSS);
break;
}
}
return result.toString();
}
private static String fillString(String strDate, String str,
String position, String addStr, int len) {
if (str.length() > len) {
String mes = strDate + “このString文字列は日付文字列に変換できません”;
throw new IllegalStateException(mes);
}
return fillString(str, position, addStr, len);
}
/**
* 文字列[str]に対して補充する文字列[addStr]を[position]の位置に[len]に
* 満たすまで挿入します。
* <p>
* 例: String ss = StringUtil.fillString(“aaa”,”b”,”0″,7); ss ⇒ “aaa0000”
*
* ※fillString()はlenに満たすまで挿入しますが、addString()はlen分挿入します。
*
* @param str 対象文字列
* @param position 前に挿入 ⇒ F/f 後に挿入 ⇒ B/b
* @param addStr 挿入する文字列
* @param len 補充するまでの桁数
* @return 変換後の文字列。 [str]がnullや空リテラルも[addStr]を[len]に
* 満たすまで 挿入した結果を返します。
*/
private static String fillString(String str, String position,
String addStr, int len) {
StringBuffer tempBuffer = null;
if (!isExist(str)) {
tempBuffer = new StringBuffer();
for (int i = 0; i < len; i++) {
tempBuffer.append(addStr);
}
return tempBuffer.toString();
} else if (str.length() != len) {
tempBuffer = new StringBuffer(str);
while (len > tempBuffer.length()) {
if (position.equalsIgnoreCase(“f”)) {
tempBuffer.insert(0, addStr);
} else {
tempBuffer.append(addStr);
}
}
return tempBuffer.toString();
}
return str;
}
}