クラスのフィールドやメソッドを表示する

Apache Commons Langのorg.apache.commons.lang3.builderパッケージには、必要に応じてオーバーライドする以下のObjectクラスのメソッドを実装するためのヘルパークラスが存在する。

メソッド ヘルパークラス 説明
public boolean equals(Object o) EqualsBuilder 等価確認
public String toString() ToStringBuilder 文字列変換
public int hashCode() HashCodeBuilder ハッシュ値変換
public int compareTo(Object o) CompareToBuilder 大小比較

上記のToStringBuilderを使用した一般的なtoStringメソッドの実装方法は以下となる。

import org.apache.commons.lang3.builder.*;

public class MyClass
{
    private String str1 = "hello world";
    private int num1 = 123;
    private double val1 = 456.789;

    @Override
    public String toString()
    {
        return ToStringBuilder.reflectionToString(this);
    }

    public static void main(String[] args)
    {
        MyClass myInst = new MyClass();
        System.out.println(myInst.toString());
    }
}

上記の実行結果から以下の出力が得られる。

MyClass@7ea987ac[str1=hello world,num1=123,val1=456.789]

上記の出力結果を見て、ToStringBuilder.reflectionToStringメソッドはどのようにしてフィールド名を列挙し、その値を得ているのだろうかと不思議に思ったので、調べて見ることにした。

Classクラスの役割

Object.getClassメソッドを使用すると、Classクラスのインスタンスを得ることができる。
Classクラスはクラスをモデル化するクラスであるが、このClassクラスのメソッドを使用して、インスタンス化されたクラスのフィールドやメソッドを列挙することができる。

【オブジェクトのフィールド名と値の表示】
    public void printFields(Object o)
    {
        for (Field f : o.getClass().getDeclaredFields()) {
            System.out.println(f.getType().toString() + " " + f.getName() + " = " + f.get(o).toString() + ";");
        }
    }
【オブジェクトのメソッド名とパラメータの列挙】
    public void printMethods(Object o)
    {
        for (Method m : o.getClass().getDeclaredMethods()) {
            System.out.print(m.getReturnType().getName() + " " + m.getName() + "(");
            String comma = "";
            for (Class<?> c : m.getParameterTypes()) {
                String name = c.getName();
                if (name.charAt(0) == '[') {
                    switch (name.charAt(1)) {
                    case 'B' :
                        name = "byte";
                        break;
                    case 'S' :
                        name = "short";
                        break;
                    case 'I' :
                        name = "int";
                        break;
                    case 'J' :
                        name = "long";
                        break;
                    case 'C' :
                        name = "char";
                        break;
                    case 'F' :
                        name = "float";
                        break;
                    case 'D' :
                        name = "double";
                        break;
                    case 'L' :
                        name = name.substring(2, name.length() - 1);
                        break;
                    default :
                        name = name.substring(1);
                        break;
                    }
                    name += "[]";
                }
                System.out.print(comma + name);
                comma = ", ";
            }
            System.out.print(");\n");
        }
    }

終わりに

ObjectクラスやClassクラスは重要な基本クラスなので、これらについて学ぶことはJavaを深く知るために必要なことだと思った。