java.beans.PropertyDescriptor(String, Class) 的混淆行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10303009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 00:28:06  来源:igfitidea点击:

Confusing behavior of java.beans.PropertyDescriptor(String, Class)

javajavabeans

提问by Steven Schlansker

I'm trying to create a PropertyDescriptor for a bean class I have. I am calling

我正在尝试为我拥有的 bean 类创建一个 PropertyDescriptor。我在打电话

new PropertyDescriptor(myProperty, myClass)

and am seeing an exception that the method "isMyProperty" does not exist. Peeking into the code a bit --

并且我看到方法“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));
}

The documentation says that it will look for "getFred" but it always uses "is" + capitalize(property)! This is in java version "1.6.0_31"

文档说它会寻找“getFred”,但它总是使用"is" + capitalize(property)! 这是在 Java 版本“1.6.0_31”中

Thoughts?

想法?

采纳答案by John Farrelly

Edit:I think I know what your problem is. If the property doesn't exist in your class, then you will get the "isProperty" method error. See my example:

编辑:我想我知道你的问题是什么。如果您的类中不存在该属性,那么您将收到“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 */
    }


Original:

原来的:

It looks like it just defaults to isProperty as the read method, and if it doesn't exists, it uses getProperty. Take a look at the getReadMethodmethod, the bit where it goes:

看起来它只是默认为 isProperty 作为读取方法,如果它不存在,则使用 getProperty。看看这个getReadMethod方法,它的位置:

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

So it's trying the isProperty method first, and if it doesn't have that method, looks for getProperty.

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

Here's the full method:

这是完整的方法:

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;
}

回答by PetroCliff

If your property is primitive boolean then PropertyDescriptor looking for "isProperty" method. If your property is boxed Boolean then PropertyDescriptor looking for "getProperty" method.

如果您的属性是原始布尔值,则 PropertyDescriptor 寻找“isProperty”方法。如果您的属性是装箱布尔值,则 PropertyDescriptor 寻找“getProperty”方法。

回答by Jin Kwon

I had a similar problem and I solved like this.

我有一个类似的问题,我是这样解决的。

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);
}

回答by Parag

I had a similar problem with a field named "ip_value". My initial getter and setter methods were getIPValue()and setIPValue()respectively. After renaming them to getIp_value()and setIp_value()respectively the issue was resolved.

我有一个名为“ip_value”的字段的类似问题。我最初的 getter 和 setter 方法分别是getIPValue()setIPValue()。将它们分别重命名为getIp_value()和 后setIp_value(),问题就解决了。