記一次lombok的問題

1、案發現場

此問題的案發現場是測試環境,爲了減小沒必要要的類,咱們這裏用一個簡單的例子進行模擬。java

lombok version:1.16.14api

jdk version:1.8oracle

上代碼:
<!-- more -->app

├─src
│  ├─main
│  │  ├─java
│  │  │  └─org
│  │  │      └─jsbxyyx
│  │  │          └─util
│  │  │                  DozerUtil.java
│  │  │
│  │  └─resources
│  └─test
│      ├─java
│      │  └─org
│      │      └─jsbxyyx
│      │          └─test
│      │                  A.java
│      │                  A1.java
│      │                  DozerTest.java
│      │
│      └─resources
package org.jsbxyyx.util;

import com.google.common.collect.Lists;
import org.dozer.DozerBeanMapper;
import java.util.Collection;
import java.util.List;

public class DozerUtil {
    private static DozerBeanMapper dozer = new DozerBeanMapper();

    public static <T> T map(Object source, Class<T> destinationClass) {
        return dozer.map(source, destinationClass);
    }
    public static <T> List<T> mapList(@SuppressWarnings("rawtypes") Collection sourceList, Class<T> destinationClass) {
        List<T> destinationList = Lists.newArrayList();
        for (Object sourceObject : sourceList) {
            T destinationObject = dozer.map(sourceObject, destinationClass);
            destinationList.add(destinationObject);
        }
        return destinationList;
    }
    public static void map(Object source, Object destinationObject) {
        dozer.map(source, destinationObject);
    }
}
package org.jsbxyyx.test;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@ToString
public class A {
    private String date;
    private String vNum;
}
package org.jsbxyyx.test;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Setter
@Getter
@ToString
public class A1 {
    private String date;
    private String vaNum;
}
package org.jsbxyyx.test;

import java.util.HashMap;
import java.util.Map;
import org.jsbxyyx.util.DozerUtil;
import org.junit.Assert;
import org.junit.Test;

public class DozerTest {
    
    @Test
    public void testA() throws Exception {
        Map<String, String> mapA = new HashMap<>();
        mapA.put("date", "2018-04-03");
        mapA.put("vNum", "123");
        A a = DozerUtil.map(mapA, A.class);
        Assert.assertEquals("123", a.getVNum());
    }
    
    @Test
    public void testA1() throws Exception {
        Map<String, String> mapA1 = new HashMap<>();
        mapA1.put("date", "2018-04-03");
        mapA1.put("vaNum", "123");
        A1 a = DozerUtil.map(mapA1, A1.class);
        Assert.assertEquals("123", a.getVaNum());
    }
}

2、案件分析

咱們執行測試用testA和testA1發現eclipse

testA紅了ide

testA1綠了測試

紅了表示測試不經過啊。。。。。咱們來看看爲啥不經過。google

問題的關鍵在於lombok生成getter,setter的時候沒有按照JavaBean的規範來生成。致使testA就紅了。idea

直接看反編譯代碼:spa

A.class

lombok a class

咱們再看看eclipse或者idea生成getter,setter是怎麼樣的

idea a class

到了這裏,咱們發現問題了,lombok的getter,setter方法生成的不對。

3、案件處理

解決辦法,去掉@Getter @Setter註解,用IDE生成,獲取覆蓋相應的getter/setter

4、案件原理追溯

那麼咱們來分析一下,標準JavaBean是如何生成的。

官方文檔:Java Beans specification

看到英語頭大有木有。。。有木有。。。有木有。。。

好咱們解釋一下。

首先咱們來描述一下JavaBean的規範

  1. Bean有一個默認的無參構造器
  2. 屬性修飾符爲private
  3. 實現接口java.io.Serializable
  4. 全部的訪問器都以get開頭,全部的修改器都用set,布爾類型訪問器用is開頭

接下來咱們來講一下javabean的getters/setters是如何生成,也就解決了問題。。

這個類Introspector.decapitalize()方法,能夠獲取到屬性

Utility method to take a string and convert it to normal Java variable name capitalization.  This normally means converting the first character from upper case to lower case, but in the (unusual) special case when there is more than one character and both the first and second characters are upper case, we leave it alone.

Thus "FooBah" becomes "fooBah" and 
"X" becomes "x", 
but "URL" stays as "URL".

意思就是第一個字母轉大寫後,若是第二個字母和轉換後的第一個字母同樣是大寫,那麼就返回原值。不然就返回首字母大寫後的值。

問題就到這裏啦。。。。。。。

原文地址:https://blog.uyiplus.com/2018/lombok-quesion-1/

相關文章
相關標籤/搜索