entityやら構造体やら、値を入れる入れ物を書くと大抵
toString()メソッドをoverrideしているかと思うわけですが、
毎回書くのは結構かったるい訳です。
DBのスキーマを元に、とかだと自動生成ツールがいろいろとあったりするわけですが、
時には自作しなければいけないもの。
で、reflectionでそこを楽にできないかなぁと調べた結果がこれ。
(下部にソース添付)
loopで10万回繰り返して、作成したentityで試してみた。
結果:
reflectionを使用したもの: 12秒358
普通にtoString()を実装 0秒180
(StringBuilderで文字を組み立てたもの)
(´・ェ・`) ・・・違い過ぎる。
うーん、マシンスペックやらを省略してますけど、それでもこんなに違うとは。
utility的にreflectionを多用したら開発が楽できるかな?
と思ったのですが後のパフォーマンスチューニングに苦しみそうですね。
それにこれ、配列とかリストとか全然対応してないし。
とすると、次なる候補はvelocityなどのTemplateEngine系になりそうです。
(使用しているFrameworkのソースをみたらおもしろそうだったので)
package jp.co.ahaha.reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import javax.persistence.Column; //geronimo-jpa_3.0_spec-1.0jar を使用
public class ReflectionSample {
/**
* 受け取ったobjectを、 フィールド名=値 の形式でカンマ区切りにした文字列表現で返却します。
* ただし、final と static で宣言された項目については呼び出す予定はありません。
* また、もしそのobjectがentityである場合(=javax.persistence.Columnアノテーションが付加されている場合)
* フィールド名の代わりに、Columnアノテーションの名前を用いて 出力します。
* こちらは、返却される文字列には改行コードは含まれません。
* @param value
* @return
*/
public static final String toValueOneLine(Object value) {
return ReflectionSample.toValue(value,false);
}
/**
* 受け取ったobjectを、 フィールド名=値 の形式でカンマ区切りにした文字列表現で返却します。
* ただし、final と static で宣言された項目については呼び出す予定はありません。
* また、もしそのobjectがentityである場合(=javax.persistence.Columnアノテーションが付加されている場合)
* フィールド名の代わりに、Columnアノテーションの名前を用いて 出力します。
* こちらは、返却される文字列の フィールド名=値のペア毎に改行します。
* @param value
* @return
*/
public static final String toValueMulti(Object value) {
return ReflectionSample.toValue(value,true);
}
final static String toValue(Object value, boolean multiLine) {
//for NullException
if (value == null) {
return "null";
}
String endOfLine = "";
if (multiLine) {
endOfLine = "\n";
}
//get public field(Seasar entity)
Field[] fields = value.getClass().getFields();
boolean accessPrivate = false;
if (fields == null || fields.length == 0) {
//get normal javaBeans
fields = value.getClass().getDeclaredFields();
accessPrivate = true;
}
StringBuilder sb = new StringBuilder(1024);
for (Field f: fields) {
if (accessPrivate) {
f.setAccessible(accessPrivate);
}
try {
//dont get Final or Static fields
if (!Modifier.isFinal(f.getModifiers()) &&
!Modifier.isStatic(f.getModifiers())) {
//columnName (fieldName)
sb.append(toFieldString(f));
sb.append("=");
//columnValue
Object temp = f.get(value);
if (temp == null) {
sb.append("null");
} else {
sb.append(temp.toString());
}
sb.append(",");
sb.append(endOfLine);
}
} catch (Exception e) {
// catch and proceed
e.printStackTrace(); //need log
}
}
return sb.toString();
}
/**
* if field has javax.persistence.Column annotation and (name is
not null) then return column.name
* else return field name
* @param f
* @return
*/
private final static String toFieldString(Field f) {
Column c = f.getAnnotation(Column.class);
if (c != null && c.name() != null) {
return c.name();
} else {
return f.getName();
}
}
}