2011-12-15 4 views
52

多くのゲッターを持つjavaクラスを作成しています。私はすべてのゲッターメソッドを取得したいと思っています。 getMethods()やgetMethod(String name、Class ... parameterTypes)などのメソッドを使用していますが、実際にgetterを取得したいのですが、regexを使用しますか?誰でも私に教えてくれますか?ありがとう!正規表現を使用しないでくださいJava Reflection:Javaクラスのすべてのゲッターメソッドを取得して呼び出すにはどうすればいいですか?

答えて

128

は、使用Introspector

通常
for(PropertyDescriptor propertyDescriptor : 
    Introspector.getBeanInfo(yourClass).getPropertyDescriptors()){ 

    // propertyEditor.getReadMethod() exposes the getter 
    // btw, this may be null if you have a write-only property 
    System.out.println(propertyDescriptor.getReadMethod()); 
} 

次の2つのパラメータを持つメソッドを使用すると思いますので、あなたは、Object.classをからプロパティを望んでいない:

Introspector.getBeanInfo(yourClass, stopClass) 
// usually with Object.class as 2nd param 
// the first class is inclusive, the second exclusive 

ところで、あなたのためにそれを行い、あなたに高いレベルの見解を提示するフレームワークがあります。例えば。検索およびすべてのゲッターを実行し、マップに結果を格納: コモン/々BeanUtilsはちょうどそれがない方法

Map<String, String> properties = BeanUtils.describe(yourObject); 

docs here)を有しています。残念ながら、BeanUtils.describe()はすべてのプロパティ値をStringに変換してから返します。 WTF。おかげ


@danw更新:

ここでは、オブジェクトのBeanプロパティに基づいてMap<String, Object>を返すJava 8の方法です。

public static Map<String, Object> beanProperties(Object bean) { 
    try { 
    return Arrays.asList(
     Introspector.getBeanInfo(bean.getClass(), Object.class) 
        .getPropertyDescriptors() 
    ) 
     .stream() 
     // filter out properties with setters only 
     .filter(pd -> Objects.nonNull(pd.getReadMethod())) 
     .collect(Collectors.toMap(
     // bean property name 
     PropertyDescriptor::getName, 
     pd -> { // invoke method to get value 
      try { 
       return pd.getReadMethod().invoke(bean); 
      } catch (Exception e) { 
       // replace this with better error handling 
       return null; 
      } 
     })); 
    } catch (IntrospectionException e) { 
    // and this, too 
    return Collections.emptyMap(); 
    } 
} 

エラー処理をより堅牢にしたいと思うかもしれません。申し訳ありませんが、定型的な例外はここで完全に機能することを妨げています。


Collectors.toMap()はnull値を嫌うことが分かります。ここでは、上記のコードの多くの不可欠のバージョンがあります:

public static Map<String, Object> beanProperties(Object bean) { 
    try { 
     Map<String, Object> map = new HashMap<>(); 
     Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class) 
            .getPropertyDescriptors()) 
       .stream() 
       // filter out properties with setters only 
       .filter(pd -> Objects.nonNull(pd.getReadMethod())) 
       .forEach(pd -> { // invoke method to get value 
        try { 
         Object value = pd.getReadMethod().invoke(bean); 
         if (value != null) { 
          map.put(pd.getName(), value); 
         } 
        } catch (Exception e) { 
         // add proper error handling here 
        } 
       }); 
     return map; 
    } catch (IntrospectionException e) { 
     // and here, too 
     return Collections.emptyMap(); 
    } 
} 

ここJavaSlangを使用して、より簡潔な方法で同じ機能です:

public static Map<String, Object> javaSlangBeanProperties(Object bean) { 
    try { 
     return Stream.of(Introspector.getBeanInfo(bean.getClass(), Object.class) 
            .getPropertyDescriptors()) 
        .filter(pd -> pd.getReadMethod() != null) 
        .toJavaMap(pd -> { 
         try { 
          return new Tuple2<>(
            pd.getName(), 
            pd.getReadMethod().invoke(bean)); 
         } catch (Exception e) { 
          throw new IllegalStateException(); 
         } 
        }); 
    } catch (IntrospectionException e) { 
     throw new IllegalStateException(); 

    } 
} 

そしてここでは、グアバのバージョンがあります:

public static Map<String, Object> guavaBeanProperties(Object bean) { 
    Object NULL = new Object(); 
    try { 
     return Maps.transformValues(
       Arrays.stream(
         Introspector.getBeanInfo(bean.getClass(), Object.class) 
            .getPropertyDescriptors()) 
         .filter(pd -> Objects.nonNull(pd.getReadMethod())) 
         .collect(ImmutableMap::<String, Object>builder, 
           (builder, pd) -> { 
            try { 
             Object result = pd.getReadMethod() 
                 .invoke(bean); 
             builder.put(pd.getName(), 
                firstNonNull(result, NULL)); 
            } catch (Exception e) { 
             throw propagate(e); 
            } 
           }, 
           (left, right) -> left.putAll(right.build())) 
         .build(), v -> v == NULL ? null : v); 
    } catch (IntrospectionException e) { 
     throw propagate(e); 
    } 
} 
+5

ワウ。私はあなたがそれを行うことができたのか分からなかった!クール! –

+0

ありがとう..iテストコードです...出力の終わりは** public final native java.lang.Class java.lang.Object.getClass()** ...私はそれを呼びたくありません。どのようにそれを削除するには? – user996505

+1

@ user996505 Introspector.getBeanInfo(yourClass、Object.class)を使用して、下のすべてのクラスを検索します。 –

9
// Get the Class object associated with this class. 
    MyClass myClass= new MyClass(); 
    Class objClass= myClass.getClass(); 

    // Get the public methods associated with this class. 
    Method[] methods = objClass.getMethods(); 
    for (Method method:methods) 
    { 
     System.out.println("Public method found: " + method.toString()); 
    } 
+1

はい、ただし、パブリックで非静的であり、voidを返し、パラメータが不要で、get/isXyzという名前の規約に従うメソッドをチェックする必要があります。 Introspectorはすべてのことを行い、BeanInfoデータを他のアプリケーションのために内部的にキャッシュします。 –

+0

はvoidを返しません。つまり、 –

16

これにはReflectionsフレームワークを使用できます。

import org.reflections.ReflectionUtils.*; 
Set<Method> getters = ReflectionUtils.getAllMethods(someClass, 
     ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get")); 
+0

です。すべてのゲッターが「get」で始まるわけではありません。(1)ブール値を返すgetterは「is」で始まることがあります。 (2)BeanInfoクラスは、追加のメソッドがゲッターであると述べることがあります。すべてのgetterが "get"で始まることを知っていれば、あなたは本当にこのような制限を加えるべきです。 – toolforger

-4

getAttribute1を(起動するように、あなたは一般的なゲッターGET(「ATTRIBUTE1」)を呼び出すことができるはずです)、すべての豆で一般的なゲッターを維持すべき

この汎用ゲッター意志でターンボーク正しいゲッター

Object get(String attribute) 
{ 
    if("Attribute1".equals(attribute) 
    { 
     return getAttribute1(); 
    } 
} 

このアプローチは、すべてのBeanに、この別のリストを維持するためにあなたを必要とするが、あなたは上記を使用することができ良好な性能を持っている必要があり、生産コードを書くかのように、この方法は、あなたは、パフォーマンスの問題を持っている反射を避けますあなたのすべての豆のパターン。

高性能の要件を持たないテストコードまたはユーティリティーコードの場合は、この一般的なゲッター関数を保証するコンパイル時チェッカーを書くことができない限り、このアプローチはエラーが起こりやすいので、すべての属性に対して機能します。

7

Springは、豆のイントロスペクションのための簡単なBeanUtil method提供しています:

PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property); 
Method getter = pd.getReadMethod(); 
0

このコードはOKテストされています。

関連する問題