2012-04-24 32 views
4

私が持っているBeanクラスのPropertyDescriptorを作成しようとしています。私は電話していますjava.beans.PropertyDescriptor(String、Class)の動作が混乱しています

new PropertyDescriptor(myProperty, myClass) 

"isMyProperty"というメソッドが存在しないという例外があります。 は、コードにビットを覗く -

/** 
* Constructs a PropertyDescriptor for a property that follows 
* the standard Java convention by having getFoo and setFoo 
* accessor methods. Thus if the argument name is "fred", it will 
* assume that the writer method is "setFred" and the reader method 
* is "getFred" (or "isFred" for a boolean property). Note that the 
* property name should start with a lower case character, which will 
* be capitalized in the method names. 
* 
* @param propertyName The programmatic name of the property. 
* @param beanClass The Class object for the target bean. For 
*  example sun.beans.OurButton.class. 
* @exception IntrospectionException if an exception occurs during 
*    introspection. 
*/ 
public PropertyDescriptor(String propertyName, Class<?> beanClass) 
    throws IntrospectionException { 
this(propertyName, beanClass, 
    "is" + capitalize(propertyName), 
    "set" + capitalize(propertyName)); 
} 

ドキュメントは、それが「getFred」を探しますと言うが、それは常に"is" + capitalize(property)を使用しています!これはJavaバージョン1.6.0_31です

考えですか?

+0

'myProperty'はブール値のプロパティですか? – srkavin

+1

これは本当にバグのようです。私の説明では、 'PropertyDescriptor'は通常、直接インスタンス化されるのではなく、' Introspector'と 'BeanInfo'を通って実行されます。それでも、これは公開APIです。 –

+0

@srjavin:ブール値かどうかはどこでチェックされますか?いいえ、この場合はそうではありません。だからこそ私は混乱して、「そうした方法はありません」という意味です。マイプロパティ。 –

答えて

6

編集:私はあなたの問題が何であるか知っていると思います。プロパティがクラスに存在しない場合、 "isProperty"メソッドのエラーが発生します。私の例を参照してください。

{ 
     PropertyDescriptor desc = new PropertyDescriptor("uuid", Company.class); 
     Method m = desc.getReadMethod(); 
     System.out.println(m.getName()); /* prints getUuid */ 
    } 
    { 
     PropertyDescriptor desc = new PropertyDescriptor("uuid11", Company.class); 
     Method m = desc.getReadMethod(); 
     System.out.println(m.getName()); /* throws Method not found: isUuid11 */ 
    } 

オリジナル:

これは、readメソッドとしてisPropertyにそれのように単にデフォルトを見て、それが存在しない場合、それはgetPropertyメソッドを使用しています。だから、最初isProperty方法をしようとしている

if (readMethod == null) { 
    readMethodName = "get" + getBaseName(); 

、及びその方法を持っていない場合、getPropertyメソッドを探します。getReadMethod方法、それが行く少し見てみましょう。あなたの財産は、その後のPropertyDescriptorは "isProperty" 方法を探しているプリミティブboolean型である場合

public synchronized Method getReadMethod() { 
Method readMethod = getReadMethod0(); 
if (readMethod == null) { 
    Class cls = getClass0(); 
    if (cls == null || (readMethodName == null && readMethodRef == null)) { 
     // The read method was explicitly set to null. 
     return null; 
    } 
    if (readMethodName == null) { 
     Class type = getPropertyType0(); 
     if (type == boolean.class || type == null) { 
      readMethodName = "is" + getBaseName(); 
     } else { 
      readMethodName = "get" + getBaseName(); 
     } 
    } 

    // Since there can be multiple write methods but only one getter 
    // method, find the getter method first so that you know what the 
    // property type is. For booleans, there can be "is" and "get" 
    // methods. If an "is" method exists, this is the official 
    // reader method so look for this one first. 
    readMethod = Introspector.findMethod(cls, readMethodName, 0); 
    if (readMethod == null) { 
     readMethodName = "get" + getBaseName(); 
     readMethod = Introspector.findMethod(cls, readMethodName, 0); 
    } 
    try { 
     setReadMethod(readMethod); 
    } catch (IntrospectionException ex) { 
    // fall 
    } 
} 
return readMethod; 
} 
+0

しかし、readMethodNameは、コンストラクタで設定されているのと同じプロパティです。つまり、isFooは、引用しているコードのビットを抑制します。実際には、コンストラクタはreadMethodNameがnullでないことをチェックします(私の場合、目的を完全に無効にするMethodオブジェクトを直接指定しない限り) –

+0

私はコードを読みやすくするために再フォーマットしました。コンストラクタで設定されているものはreadMethodNameです。これが設定されている場合、Introspector.findMethod(readMethodName)が呼び出され、nullが返された場合はgetメソッドが検索されます。 –

+1

うわー、JDKの中で見つかるすごいコードは...これを書くには約50の明確な方法があります:P –

2

はここで完全な方法です。 プロパティがboxedの場合は、PropertyDescriptorが「getProperty」メソッドを探します。

+0

これはまさに私たちの問題でした。非常に明白ではなく、非常に迷惑な、見つけるのに長い時間がかかりました! –

0

私も同様の問題がありましたが、このように解決しました。

static Object get(final String name, final Object obj) 
    throws ReflectiveOperationException { 

    final Class<?> klass = obj.getClass(); 

    try { 
     final BeanInfo info = Introspector.getBeanInfo(klass); 
     for (final PropertyDescriptor descriptor 
      : info.getPropertyDescriptors()) { 
      if (name.equals(descriptor.getName())) { 
       final Method reader = descriptor.getReadMethod(); 
       if (reader != null) { 
        if (!reader.isAccessible()) { 
         reader.setAccessible(true); 
        } 
        return reader.invoke(obj); 
       } 
       break; // anyway 
      } 
     } 
    } catch (final IntrospectionException ie) { 
     ie.printStackTrace(System.err); 
    } 

    final Field field = findField(obj.getClass(), name); 
    logger.log(Level.WARNING, "trying to get value directly from {0}", 
       new Object[]{field}); 
    if (!field.isAccessible()) { 
     field.setAccessible(true); 
    } 
    return field.get(obj); 
} 
0

「ip_value」という名前のフィールドで同様の問題が発生しました。 私の最初のゲッターメソッドとセッターメソッドはそれぞれgetIPValue()setIPValue()でした。 getIp_value()setIp_value()にそれぞれ名前を変更した後、問題は解決しました。

関連する問題