LoginSignup
1
0

More than 5 years have passed since last update.

リフレクションユーティリティを作る②

Last updated at Posted at 2019-03-25

今回は引数のオブジェクトのフィールドを適当な値で埋めるメソッドです。
JUnitで「あるオブジェクトに対してなんでもいいからとりあえずフィールド埋めている状態にしたい、でもいちいちsetter呼ぶの面倒臭すぎ!」ってことよくありますよね。そういう時に適当にフィールドに値を詰めてくれるメソッドを作ってみました。

前回作ったもの→プライベートメソッドを実行するやつ

作成したユーティリティメソッド

ReflectionUtil.java
public static void fillAllFields(Object obj, int offset) throws IllegalArgumentException, IllegalAccessException {
    Assertions.assertThat(offset >= 0);
    boolean b = true;
    char c=(char) (65 + offset); // A+

    Field[] fieldList = obj.getClass().getDeclaredFields();
    for (int i = 0; i < fieldList.length; i++) {
        int num = i + offset;
        Field f = fieldList[i];
        f.setAccessible(true);
        String name = f.getName();
        Class<?> clazz = f.getType();

        if (Modifier.isFinal(f.getModifiers())) {
            continue;
        }
        if (clazz == String.class) {
            f.set(obj, name + num);
        } else if (clazz == Date.class) {
            Calendar calendar = Calendar.getInstance();
            int d = num % 28;
            calendar.set(2019, Calendar.MARCH, d);
            f.set(obj, calendar.getTime());
        } else if (clazz == Timestamp.class) {
            Calendar calendar = Calendar.getInstance();
            int d = num % 28;
            calendar.set(2019, Calendar.MARCH, d);
            f.set(obj, new Timestamp(calendar.getTimeInMillis()));
        } else if(clazz==boolean.class ||clazz==Boolean.class ){
            f.set(obj, b);
            b=!b;
        } else if(clazz==BigDecimal.class){
            f.set(obj, new BigDecimal(num));
        } else if(clazz==int.class||clazz==Integer.class){
            f.set(obj, num);
        } else if(clazz==long.class||clazz==Long.class){
            f.set(obj, ((Integer) num).longValue());
        } else if(clazz==float.class||clazz==Float.class){
            f.set(obj, ((Integer) num).floatValue());
        } else if(clazz==double.class||clazz==Double.class){
            f.set(obj, ((Integer) num).doubleValue());
        } else if(clazz==short.class||clazz==Short.class){
            f.set(obj, ((Integer) num).shortValue());
        } else if(clazz==byte.class||clazz==Byte.class){
            f.set(obj, ((Integer) num).byteValue());
        } else if(clazz==char.class||clazz==Character.class){
            if (c < 65 || 90 < c) c = 65;
            f.set(obj, ((char) c));
            c++;
        }
    }
}

動かしてみる

適当なPOJOを用意

EntityA.java
@Data
public class EntityA {
    private String str;
    private Date date;
    private Timestamp ts;
    private Boolean bool;
    private BigDecimal bd;
    private Integer i;
    private long l;
    private Float f;
    private double d;
    private Short s;
    private byte b;
    private Character c;
}

テストメソッド

Tests.java
@Test
public void test1() {
    EntityA entity= new EntityA();
    try {
        ReflectionUtil.fillAllFields(entity, 25);
        System.out.println(entity);
    } catch (IllegalArgumentException | IllegalAccessException e) {
        e.printStackTrace();
        fail();
    }
}

実行結果

コンソール
EntityA(str=str25, date=Tue Mar 26 02:05:01 JST 2019, ts=2019-03-27 02:05:01.786, bool=true, bd=29, i=30, l=31, f=32.0, d=33.0, s=34, b=35, c=Z)

あとがき

ミソはcharの場合にどうするかですね。このメソッドでは大文字のアルファベットA-Zに絞っています。
他のクラスは必要に応じて随時追加ですね。
境界値の検証してないのでバグあったらすみません。

おもいっきりレガシーなJavaメソッドになったけど、本当は出来る限りJava8を取り入れたかった。

というか、そもそもこんなユーティリティは何かのライブラリにあったりしそう??

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0