2012-04-24 101 views
4

我想为我有的bean类创建一个PropertyDescriptor。我打电话混淆java.beans.PropertyDescriptor的行为(字符串,类)

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 2012-04-24 17:56:18

+1

这真的看起来像一个错误。我的解释是'PropertyDescriptor'通常不是直接实例化的,而是通过'Introspector'和'BeanInfo'实现的。不过,这是公共API。 – 2012-04-24 18:54:36

+0

@srjavin:它甚至在哪里检查它是否是布尔值?不,在这种情况下它不是 - 这就是为什么我很困惑,我得到“没有这样的方法isMyProperty” – 2012-04-24 19:21:02

回答

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 */ 
    } 

原文:

看起来它只是默认为isProperty作为读取方法,如果不存在的话,它使用的getProperty。看看在getReadMethod方法,该位,哪里就有奇迹:

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

所以它首先尝试isProperty方法,如果没有该方法,查找的getProperty。

下面是完整的方法:

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是否为空(除非直接指定Method对象,这完全违背了我的情况) – 2012-04-24 19:48:40

+0

我已将代码重新格式化,使其更易于阅读。 readMethodName是在构造函数中设置的。如果设置了,它将调用Introspector.findMethod(readMethodName),如果返回null,它会查找“get”方法。 – 2012-04-24 19:52:07

+1

哇,在JDK中找到什么可怕的代码...有大约50种更清晰的方式来编写它:P – 2012-04-27 22:41:07

2

如果你的财产是原始布尔然后PropertyDescriptor的寻找“isProperty”的方法。 如果你的属性是装箱布尔值,然后PropertyDescriptor寻找“getProperty”方法。

+0

这正是我们的问题。非常不明显,非常烦人,花了很长时间才找到! – 2014-07-11 11:37:33

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”场类似的问题。 我最初的getter和setter方法分别是getIPValue()setIPValue()。 分别将它们重命名为getIp_value()setIp_value()后,问题得到解决。