toString()をリフレクションで書きたい。
debug用等でフィールドをtoStringするときは、まぁ適当に書くとこんな感じですね。
@Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("key:").append(key).append(","); sb.append("name:").append(name).append(","); sb.append("sex:").append(sex).append(","); sb.append("age:").append(age); return sb.toString(); }
実行結果
key:aaa,name:bbb,sex:ccc,age:ddd
でも、これだとフィールドがやたら多い場合に面倒です。
なにより、見栄えが悪い。。
ということで、リフレクションの使用を検討してみたいと思います。
リフレクションを使ってみよう
リフレクションのメリデメ
- メリット:記述量が少なくなる。共通処理として抜き出せる。
- デメリット:遅い。セキュリティマネージャにひっかかるかも?
Beanはとりあえず、こんなのを用意しました。
public class TestBean { private String key; private String name; private String sex; private String age;
さて、
フィールドをリフレクションで取得するには
java.lang.Class#getDeclaredFields()でjava.lang.reflect.Field[] を取得してやればいいらしい。
@Override public String toString() { StringBuilder sb = new StringBuilder(); Field[] fields = this.getClass().getDeclaredFields(); for (Field field : fields) { sb.append(field.getName()); } return sb.toString(); }
実行結果
keynamesexage
フィールド名がそのまま取れた。
そりゃそうか。ここからどうすればいいんだろう?
java.lang.reflect.Field#get(object)を使ってみる。
@Override public String toString() { StringBuilder sb = new StringBuilder(); Field[] fields = this.getClass().getDeclaredFields(); for (Field field : fields) { try { sb.append(field.get(this)); } catch (IllegalAccessException e) { e.printStackTrace(); } } return sb.toString(); }
実行結果
aaabbbcccddd
おお、出た!
整形してないので、ずらずら出てるだけだけど。。
あれ?
そういや、java.lang.reflect.Field#setAccessible(true)ってのをしないと、
privateフィールドへのアクセスは例外になるはずなんだが・・・?
試しに、入れてみても実行結果は変わらず。。
なぜ??
まぁ、いいか。
追記:
java.lang.reflect.Field#setAccessible(true)は、privaetフィールドへのアクセスを
許容するという宣言。
今回のサンプルでは、同クラス内のtoStringからprivateフィールドにアクセスしているため、
特に制限がない。(自クラス内からアクセス出来るのは当たり前)
なので、他のクラスのprivateフィールドにアクセスするときは、上記のメソッドで制限を
はずさなければいけない。
整形してみた。
@Override public String toString() { StringBuilder sb = new StringBuilder(); Field[] fields = this.getClass().getDeclaredFields(); for (Field field : fields) { try { sb.append(field.getName() + "=" + field.get(this) + ", "); } catch (IllegalAccessException e) { e.printStackTrace(); } } return sb.toString(); }
実行結果
key=aaa, name=bbb, sex=ccc, age=ddd,
最後のカンマはめんどくてとってないけど、いい感じ。
時間切れなので、今日はここまで。
次はフィールドが配列や、Beanの場合を考えてみよう。