QA@IT

Java で任意のクラスのフィールド名を取得する方法

7765 PV

Javaであるクラスの項目名を取得する方法を探しています。
実際に行いことは、あるDBサービスクラスに、エンティティクラスの項目名と、
検索対象の値を渡し、検索結果を得るような処理(S2jdbcのSimpleWhere 等)で、
項目名のパラメーターを、クラス情報から得たいのです。

  DbWhereSearch dws = new DbWhereSearch();
  dws.eq("hoge" , prmHoge);
  // この第一パラメーターを下記のように、クラス情報から指定したい。
  dws.eq(getFieldName(foo.this.hoge), prmHoge);

  return search(dws).getResult();

getFields() で、クラスが持つフィールドのマップは取得できますが、
キーが項目名ですので、結局項目名を定数として指定する必要があり、
今回の目的を解決することはできません。

以上、よろしくお願いします。

回答

思い付きで、しかもインターフェースじゃないとダメですが。

MethodNameProxyMaker.java

package atmarkitsample.methodnameproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MethodNameProxyMaker {

    public <T> T makeProxy(
            final Class<T> mainInterface) {

        final Class<?>[] interfaces = new Class<?>[]{ mainInterface };

        @SuppressWarnings("unchecked")
        final T proxy = (T) Proxy.newProxyInstance(
                StubForMethodname.class.getClassLoader(),
                interfaces,
                new AlwaysReturnMethodNameInvocationHandler());

        return proxy;

    }

    public class AlwaysReturnMethodNameInvocationHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            final String name = method.getName();
            return name;
        }

    }

    public class StubForMethodname{
    }

}

SampleMain.java

package atmarkitsample.methodnameproxy;

public class SampleMain {

    /**
     * @param args
     */
    public static void main(String[] args) {

        MethodNameProxyMaker proxyMaker = new MethodNameProxyMaker();
        TableA tableA = proxyMaker.makeProxy(TableA.class);
        TableB tableB = proxyMaker.makeProxy(TableB.class);

        System.out.println(tableA.columnA());
        System.out.println(tableB.columnE());

    }

    interface TableA{
        String columnA();
        String columnB();
    }

    interface TableB{
        String columnE();
        String columnF();
    }

}

実行結果を追記
実行結果

columnA
columnE
編集 履歴 (2)
  • インターフェースのメソッドの戻り値の型はString決め打ちです。つまりかなり乱暴(笑)。 -
  • 回答ありがとうございます、参考にさせていただきます。 -

こういうことでしょう。

同様の問題の存在にたいしてソースを二重管理状態にするのはいかがなものかとおもったんだが。
なんか苦情きてるのであげとく。

コメントはリンクがされません。
コメントのリンクで解決した場合も自己解決ではありません。


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;


public class Main {


    public static void main(String[] args) {

        Class<A> clazz = A.class;

        System.out.println("Field");
        Field[] fields = clazz.getDeclaredFields();

        for (Field field : fields) {
            System.out.println(field.getName());
        }

        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
            Type[] types = method.getParameterTypes();
            if (types != null && types.length > 0) {
                System.out.println("引数");
                for (Type type : types) {
                    System.out.println(type.toString());
                }
            }
        }

    }

}

     class A {
        private final int fint;

        public A(int fint) {
            this.fint = fint;
        }

        public A() {
            this(0);
        }

        public String field1;
        public String field2;

        public String method1() {
            return method1("1");
        }

        public String method1(String a) {
            return a;
        }

    }
編集 履歴 (1)
  • 回答ありがとうございます。
    ご紹介いただいた方法では、結局目的のフィールドが何番目に存在するかを指定する必要があり、結局クラス定義とは別に、別途クラスの持つフィールの定義(フィールド名 or フィールド名配列のインデックス)を行う必要でてしまいます。
    クラスの定義と項目の定義を二重に行わずに、項目名を取得する方法をもう少し探してみます。

    ありがとうございました。
    -
  • ちなみに、フィールドの順番は上から記載順にでます・w・ -
  • administratorさん、ガイドラインに書いてあるのですが、リンクを示すだけの回答はやめてください。 -
  • 自作ですが?なにか ソースを2重に投稿すれということですか・w・?そういうなら ソースもこっちに投稿しておきます。 -
  • リンクだけだとその先がどこか、何があるのかわかりにくいのは困る、参考になる投稿ならなおさら勿体無い。という程度の事かと思いますよ。 -
  • administrator さんは退会したようです。後からここを見る人がいるかもいれないので書いておきますが、「分からない」といって困っている人に対して、なにもぶっきらぼうに言うことないではありませんかという話です。そもそもコード例だけで説明ゼロというのも、不親切というより、ほとんど高圧的だと思います。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。