Java Beans、BeanUtils和布尔包装类

17

我正在使用BeanUtils来操作通过JAXB创建的Java对象,但我遇到了一个有趣的问题。有时,JAXB会创建类似于这样的Java对象:

public class Bean {
    protected Boolean happy;

    public Boolean isHappy() {
        return happy;
    }

    public void setHappy(Boolean happy) {
        this.happy = happy;
    }
}

以下代码完全正常:

Bean bean = new Bean();
BeanUtils.setProperty(bean, "happy", true);

然而,尝试像这样获取 happy 属性:

Bean bean = new Bean();
BeanUtils.getProperty(bean, "happy");

导致此异常的结果:

Exception in thread "main" java.lang.NoSuchMethodException: Property 'happy' has no getter method in class 'class Bean'
改变所有内容为原始类型 boolean 可以使得get和set调用都有效。但是我无法这样做,因为这些是自动生成的类。我猜测这是因为Java Bean库仅将is<name>方法视为属性,如果返回类型是原始类型boolean而不是包装类型Boolean。请问有没有人有关于如何通过BeanUtils访问这些属性的建议?是否有某种解决方法可用?

5
BeanUtils类来自哪里?我已经检查过org.apache.commons.beanutils.BeanUtils(1.8.3),它能正常工作。请注意,通常在boolean上使用前缀is,而在Boolean上使用get - Tomasz Nurkiewicz
我正在使用相同的BeanUtils。您能够使用返回Boolean包装类的is方法执行getProperty()吗? - Charles Hellstrom
2
你关于is<name>的假设是正确的。isXXX只适用于布尔类型的返回值。对于布尔类型的返回值,getXXX是正确的方法名。 - DwB
1
你是对的,getProperty() 不能与 Boolean is 一起使用。实际上,IntelliJ 为 Boolean 生成带有 get 的 getter 方法,而为 boolean 生成带有 is 的 getter 方法 - 我猜 Eclipse 也是这样做的。 - Tomasz Nurkiewicz
3个回答

10

我终于找到了法律确认:

8.3.2 布尔属性

此外,对于布尔属性,我们允许 getter 方法与以下模式匹配:

public boolean is<PropertyName>();

引自 JavaBeans 规范。你确定你没有遇到JAXB-131的 bug 吗?


2
是的,看起来我遇到了那个 bug。我将我的 JAXB 版本升级到了 2.1.13,并添加了“-enableIntrospection”标志。这将所有 Boolean 包装器的 is 方法更改为 get。谢谢! - Charles Hellstrom

8

使用BeanUtils处理Boolean isFooBar()的方法

  1. 创建新的BeanIntrospector。

private static class BooleanIntrospector implements BeanIntrospector{
    @Override
    public void introspect(IntrospectionContext icontext) throws IntrospectionException {
        for (Method m : icontext.getTargetClass().getMethods()) {
            if (m.getName().startsWith("is") && Boolean.class.equals(m.getReturnType())) {
                String propertyName = getPropertyName(m);
                PropertyDescriptor pd = icontext.getPropertyDescriptor(propertyName);

                if (pd == null)
                    icontext.addPropertyDescriptor(new PropertyDescriptor(propertyName, m, getWriteMethod(icontext.getTargetClass(), propertyName)));
                else if (pd.getReadMethod() == null)
                    pd.setReadMethod(m);

            }
        }
    }

    private String getPropertyName(Method m){
        return WordUtils.uncapitalize(m.getName().substring(2, m.getName().length()));
    }

    private Method getWriteMethod(Class<?> clazz, String propertyName){
        try {
            return clazz.getMethod("get" + WordUtils.capitalize(propertyName));
        } catch (NoSuchMethodException e) {
            return null;
        }
    }
}

  1. 注册 BooleanIntrospector:

    BeanUtilsBean.getInstance().getPropertyUtils().addBeanIntrospector(new BooleanIntrospector());


(说明:此段代码是Java语言中关于注册BooleanIntrospector的示例,其作用是将Boolean类型的属性名前缀"is"转换为"get",以便在使用BeanUtils等工具类时能够正确识别属性名。)

很好的内容!但我认为还需要做两个更改:在getWriteMethod中,应该是“set” - 另外,直到我改用接收参数类型的重载方法后,才避免了MethodNotFoundException异常:return clazz.getMethod("set" + WordUtils.capitalize(propertyName), Boolean.class); - Jmoney38

0

你可以通过创建第二个带有 SET 后缀的 getter 方法来解决这个问题 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接