影落离风

The shadow falls away from the wind

0%

利用反射对层级对象取其某层对象的某个值,可忽略层对象不存在

前言

业务中取对象某个值时,经常会遇到对象不存在。当然只有一层对象嵌套的时候,使用Optional.ofNullable是最简单的。那要是我的对象嵌套了5层、10层,别惊讶,千奇百怪的业务总有会遇到的。要取最底层的某个值,那Optional就要写老长一串了,这就比较头疼了。

想法

还是利用反射,一层一层剥开你对象的心,看Ta是不是真心。

如要拿到a对象中有个b属性对象中有个c属性的值,可以传字符串“b.c”构造get方法利用反射获取对现象值

为什么说还是“还是利用反射”呢??看过我博客的人都知道,我的很多轮子都是用的反射,反射真强大!!如果能用的很熟练,会简化很多的撸码工作。相信我、没戳的。

利用反射的轮子😜

  1. 对视图模型构造相关参数的轮子
  2. 如何对集合对象求合计,然后追加在该集合对象中
  3. pojo转vo更简便、更优化

代码

层级对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 学生类
*
* @author MinWeikai
* @date 2021/4/3 12:30
*/
@Builder
@Data
public class Student {

private String name;


private Schoolbag bag;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 书包类
*
* @author MinWeikai
* @date 2021/4/3 12:31
*/
@Builder
@Data
public class Schoolbag {

private String color;

private PencilCase pencilCase;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 铅笔盒
*
* @author MinWeikai
* @date 2021/4/3 12:55
*/
@Builder
@Data
public class PencilCase {

private String name;

private Integer num;
}

MyOptional工作类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mwk.entity.Schoolbag;
import com.mwk.entity.Student;

import java.util.Objects;
import java.util.Optional;

/**
* @author MinWeikai
* @date 2021/4/3 12:57
*/
public final class MyOptional {


/**
* 获取层级对象的值通过层级属性
*
* @param <T>
* @param source 源对象
* @param filed 可为层级属性,属性名用小圆点.分隔
* @param vClass 属性类型
* @return
*/
public static <T> T getValueByField(Object source, String filed, final Class<T> vClass) {
Objects.requireNonNull(filed);
String[] filedNames = filed.split("\\.");
Object oldTemp;
if (filedNames.length == 1) {
oldTemp = ReflectionUtil.invokeGetterMethodNoThrowException(source, filed);
return new ObjectMapper().convertValue(oldTemp, vClass);
}
oldTemp = ReflectionUtil.invokeGetterMethodNoThrowException(source, getFirstStrByPoint(filed));
if (Objects.isNull(oldTemp)) {
return null;
}
oldTemp = getValueByField(oldTemp, getEndStrByPoint(filed), vClass);
return new ObjectMapper().convertValue(oldTemp, vClass);
}

/**
* 获取层级对象的值通过层级属性
* 被Optional修饰,可使用Optional中方法处理结果值
*
* @param source
* @param filed
* @param vClass
* @param <T>
* @return
*/
public static <T> Optional<T> ofNullable(Object source, String filed, final Class<T> vClass) {
return Optional.ofNullable(getValueByField(source, filed, vClass));
}


private static String getFirstStrByPoint(String str) {
return str.substring(0, str.indexOf("."));
}

private static String getEndStrByPoint(String str) {
return str.substring(str.indexOf(".") + 1);
}


public static void main(String[] args) {
Student student = new Student("李明",
new Schoolbag("黄色",
null));
// new PencilCase("中性笔", 2)));

System.out.println(getValueByField(student, "name", String.class));
System.out.println(getValueByField(student, "bag", Schoolbag.class));
System.out.println(getValueByField(student, "bag", Schoolbag.class).getColor());
System.out.println(getValueByField(student, "bag.color", String.class));
System.out.println(getValueByField(student, "bag.pencilCase.num", Integer.class));

// 随意测试值,找不到应该为null
System.out.println(getValueByField(student, "ww.ee.num", Integer.class));
System.out.println(getValueByField(student, "bag.ee.num", Integer.class));
System.out.println(getValueByField(null, "bag.ee.num", Integer.class));

System.out.println("-----------被Optional修饰的方法------------");
System.out.println(ofNullable(student, "bag", Schoolbag.class).map(Schoolbag::getColor).orElse("无色"));
System.out.println(ofNullable(student, "name", String.class));
System.out.println(ofNullable(student, "bag", Schoolbag.class).isPresent());
System.out.println(ofNullable(null, "bag.ee.num", Integer.class).orElse(0));
System.out.println(ofNullable(null, "bag.ee.num", Integer.class).get());

}

}

方法中用到了一个反射方法工具

ReflectionUtil工具地址