たなちの備忘録

自分の知識をストックしていくためのブログ

BeanUtils.copyProperties でBoolean型の値がnullになってしまう

スポンサーリンク

BeanUtils.copyProperties でBoolean型の値を設定しようとしても設定されずnullのままという現象が起きた。

import org.apache.commons.beanutils.BeanUtils;

TestDto testDto= new TestDto ();
TestDto valueDto= new TestDto ();

valueDto.setFlag = true;

BeanUtils.copyProperties( testDto , valueDto );
public class TestDto {

    private Boolean Flag;

    public Boolean isFlag() {
        return Flag;
    }

    public void setFlag(Boolean flag) {
        Flag = flag;
    }
}

Boolean のアクセサに isXXXを使ってはいけない

結論から書くとgetterをgetXXXではなく、isXXXで書いていたことがまずかった。isXXXはBoolean型のReadMethodとして認識されない。

こちらの記事が参考になった。 Boolean のアクセッサーに isXXX は有りか? - A Memorandum

実際にPropertyDescriptor.getReadMethod()を確認してみると、下記のようになってboolean.classの場合のみisXXXをReadMethod()として認識するようだ。

    public synchronized Method getReadMethod() {
        Method readMethod = this.readMethodRef.get();
        if (readMethod == null) {
            Class<?> cls = getClass0();
            if (cls == null || (readMethodName == null && !this.readMethodRef.isSet())) {
                // The read method was explicitly set to null.
                return null;
            }
            String nextMethodName = Introspector.GET_PREFIX + getBaseName();
            if (readMethodName == null) {
                Class<?> type = getPropertyType0();
                if (type == boolean.class || type == null) {
                    readMethodName = Introspector.IS_PREFIX + getBaseName();
                } else {
                    readMethodName = nextMethodName;
                }
            }

            // 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.equals(nextMethodName)) {
                readMethodName = nextMethodName;
                readMethod = Introspector.findMethod(cls, readMethodName, 0);
            }
            try {
                setReadMethod(readMethod);
            } catch (IntrospectionException ex) {
                // fall
            }
        }
        return readMethod;
    }

ちなみにBoolean型とboolean型の違いがよくわからない人はこの記事が役に立つ。

図で理解するJavaの参照 - Qiita

Javaの型にはプリミティブ型(基本データ型)と参照型と二種類の型が存在します。プリミティブ型は全て小文字で始まる型で、メモリに直接書き込まれる具体的なデータ値(数値や文字)を代入することができます。それと参照型と違いメソッドを持たないのも特徴の一つと言えます。

今回の場合は、Booleanが参照型でbooleanがプリミティブ型。nullは参照型変数にのみ代入できる。

その他参考記事

java - BeanUtils.setProperty not working for Boolean values? - Stack Overflow