こんにちは。「Javaを復習する初心者」です。
今回はアノテーションが付与されたフィールドをアノテーションに記述された値の順番で出力することをやりました。
自作する
アノテーションを次のように定義しました。フィールドに順序を定義するためのアノテーションです。
MyFieldOrder
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyFieldOrder {
int value();
}
アノテーションの定義自体にアノテーションを付与しています。「@Targe」はアノテーションを付与できる範囲を定義するときに使います。上記で使っている「ElementType.FIELD」の場合、アノテーションはフィールドのみに付与できます。「@Retention(RetentionPolicy.RUNTIME)」はリフレクションでアノテーションの情報を取得できるために必要です。
「int value();」と記述することにより、「@MyFieldOrder(value=1)」という具合にアノテーションを使うことができます。
フィールドに付与
TestDtoクラスを作り、次のようにアノテーションをフィールドに付与しました。
TestDto
public class TestDto {
@MyFieldOrder(value=2)
private String name;
@MyFieldOrder(value=1)
private String age;
private String note;
@Override
public String toString() {
return "TestDto [name=" + name + ", age=" + age + ", note=" + note + "]";
}
}
3つのフィールドのうち、2つに「@MyFieldOrder」を付与しています。
以下、ソースと実行結果です。
ソース
// フィールドを全て取得
Field[] fields = TestDto.class.getDeclaredFields();
System.out.println("全て取得");
for (Field field : fields) {
System.out.println(field.getName());
}
System.out.println("");
// MyFieldOrderが付与されているフィールドのみ格納
Set<Field> set = new TreeSet<>((o1, o2) -> {
MyFieldOrder myFieldOrder1 = o1.getAnnotation(MyFieldOrder.class);
MyFieldOrder myFieldOrder2 = o2.getAnnotation(MyFieldOrder.class);
return myFieldOrder1.value() - myFieldOrder2.value();
});
for (Field field : fields) {
if (field.getAnnotation(MyFieldOrder.class) != null) {
set.add(field);
}
}
System.out.println("MyFieldOrderの順番で出力");
for (Field field : set) {
System.out.println(field.getName());
}
System.out.println("");
// 順序を考慮して格納
String[] values = {"21", "name1"};
TestDto dto = new TestDto();
int index = 0;
try {
for (Field field : set) {
field.setAccessible(true);
field.set(dto, values[index++]);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(dto);
結果
全て取得
name
age
note
MyFieldOrderの順番で出力
age
name
TestDto [name=name1, age=21, note=null]
最初にフィールドすべてを取得しています。「TestDto.class.getDeclaredFields()」ではprivateフィールドも取得できます。
フィールドをアノテーションのvalue値の順番にするために、今回はTreeSetに格納することにしました。コンストラクタにComparatorの実装クラスを指定することで、順番を定義しています。[インスタンス].getAnnotation(MyFieldOrder.class)という記述で、@MyFieldOrderを取得できます。付与されていない場合、nullになり、のちの処理でエラーが発生するため、TreeSetに格納するFieldをアノテーションが付与されたものに限定しています。
最後に、具体例としてString配列の値を順番にフィールドに格納することをやっています。String配列は例えばCSVファイル等のデータだと仮定して、TestDtoのフィールドに格納するということをやっています。privateフィールドなのでsetAccessible(true)を記述しています。あとはsetメソッドで値を格納するだけです。出力結果「TestDto [name=name1, age=21, note=null]」でnameとageに値が格納されているのが確認できます。