Java-lombok及一些坑

Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率。例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量,一旦修改属性,就容易出现忘记修改对应方法的失误。

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

pom :

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
    <scope>provided</scope>
</dependency>

entity :

注解意思不做说明,不清楚的可自行查资料.
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
@ApiModel(value="XxxxVoimplements ",description="xxxxx")
@SuppressWarnings("serial")
public class XxxxVoimplements Serializable {
	@ApiModelProperty(value = "唯一标识ID",required = true,example = "10")
	@NotNull(message = "唯一标识ID不能为空")
	private Long id;
}

这里仅对@Builder做下说明 :

原实例化方式 : 
A a = new A(x,x,x,);
a.setX();
使用@Builder后 : 
A a = A.builder().id(1l).build(); 

解决的问题 : 
构造方法不确定,或者参数传参不确定时,可通过这个进行不同的传参.

坑1 : 空构造方法

问题 : 
使用@Data注解,不增加@NoArgsConstructor, 当进行copy属性时会报错,因为无空构造函数,导致实例化失败.
解决方案 : 
@Data
@NoArgsConstructor
@AllArgsConstructor

坑2 : @Builder继承

问题 : 
@Builder使用extends,如B extends A, A可以使用A.builder().id(1l).build(); 但是B不能.
解决方案 : 
1> 使用@SuperBuilder
2> 升级lombok版本,升级到1.18.6就可以了.

坑3 : 属性copy,实体类转换

问题 : 
子类属性无法copy到父类,父类属性无法copy到子类
解决方案 : 
	/**
	 * 子类转到父类
	 * @param obj 转换的源对象
	 * @param clz 目标对象
	 * @return 转换后的对象
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> T transToSuper(Object obj, Class clz) {
		T result = null;
		try {
			if (obj != null && !"".equals(obj)) {
				result = (T) clz.newInstance();
				Map<String, Field> destPropertyMap = new HashMap<>();
				for (Field curField : clz.getDeclaredFields()) {
					destPropertyMap.put(curField.getName(), curField);
				}
				for (Field curField : obj.getClass().getDeclaredFields()) {
					Field targetField = destPropertyMap.get(curField.getName());
					if (targetField != null) {
						targetField.setAccessible(true);
						curField.setAccessible(true);
						targetField.set(result, curField.get(obj));
					}
				}
				// **解决子类属性无法copy到父类** : getSuperclass一下即可.
				for (Field curField : obj.getClass().getSuperclass().getDeclaredFields()) {
					Field targetField = destPropertyMap.get(curField.getName());
					if (targetField != null) {
						targetField.setAccessible(true);
						curField.setAccessible(true);
						targetField.set(result, curField.get(obj));
					}
				}
				// **解决父类属性无法copy到子类** : copyProperties
				BeanUtils.copyProperties(obj, clz);
			}
		} catch (Exception e1) {
			log.error("e1:{}.",e1.getMessage());
			throw new BusinessException(ResultConsts.ERROR_STATUS, "实体类转换异常");
		}
		return result;
	}

BeanUtils :

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class BeanUtils extends BeanUtil {

    /**
     * <T>目标对象须含有无参构造器
     * @param source 源对象
     * @param c 目标对象class
     * @param <T> 目标对象类型
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T> T copyProperties(Object source, Class<T> c) {
        T t = null;
        try {
            t = c.newInstance();
        } catch (Exception e) {
            log.error("创建对象失败,可能缺少无参构造:{}", e.getMessage());
            throw new RuntimeException(e);
        }
        BeanUtil.copyProperties(source, t);
        return t;
    }

    /**
     *  列表数据拷贝
     * @param list 源对象列表
     * @param c 目标对象class
     * @param <T> 目标对象类型
     * @return
     */
    public static <T> List<T> copyProperties(List<?> list, Class<T> c) {
        List<T> resultList = new ArrayList<>();
        for (Object obj : list) {
            T t = copyProperties(obj, c);
            resultList.add(t);
        }
        return resultList;
    }
}
发布了67 篇原创文章 · 获赞 10 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_17522211/article/details/94382046