java反射获取对象属性实战及工具类

java反射获取对象属性实战及工具类

Posted by John Doe on 2023-03-04
Words 1.7k and Reading Time 8 Minutes
Viewed Times

什么是反射

反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制。

反射机制的功能

Java反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。

反射的使用

运行时构造修改对象

假定需求: 将List集合中reward = true的对象的score属性置为”100”,这里用反射实现举例。

1
2
3
4
5
6
@Data
public class Student {
private String name;
private String score;
private Boolean reward;
}
1
2
3
4
5
6
7
8
9
10
11
private List<Student> getReForecastDataView(List<Student> students) {
for(Student student : students) {
if(student.getReward) {
Field[] declaredFields = ForecastingOCUnionCategoryVO.class.getDeclaredFields();
Field field = Student.getClass().getDeclaredField("score");
field.setAccessible(true);
field.set(student, "100");
}
}
return students;
}
获取特定注解的值并收集到集合中

假定需求,一个billing 对象有十二个月份属性,值为对应月份产生的消耗,现在要将未发生月份置为0,已发生月份置为原来的值加上1(value = value + 1), 当前月份置为1。

Billing对象,月份属性添加特殊注解便于区分属性。

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
@Data
public calss Billing {
private String name;

@CalculateField
private Integer jan;

@CalculateField
private Integer feb;

@CalculateField
private Integer mar;

@CalculateField
private Integer apr;

@CalculateField
private Integer may;

@CalculateField
private Integer jun;

@CalculateField
private Integer jul;

@CalculateField
private Integer aug;

@CalculateField
private Integer sep;

@CalculateField
private Integer oct;

@CalculateField
private Integer nov;

@CalculateField
private Integer dec;
}
1
2
3
4
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CalculateField {
}
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
private static final List<String> monthsList = Arrays.asList("jul", "aug", "sep", "oct", "nov", "dec", "jan", "feb", "mar", "apr", "may", "jun");

/**
* 获取已发生月份
*/
private List<String> getPastMonth(String fiscalYear){
List<String> resultList = new ArrayList<>();
String currentMonth = YearMonth.now().toString();
for (String month : monthsList) {
int year = LocalDate.getYear();
month = getMonth(year, month);
// before now
if(StringUtils.compare(month, currentMonth) < 0) {
resultList.add(month);
}
}
return resultList;
}

public static String getMonth(String year, String monthAd) {
Integer monthNumber = MonthNumberEnum.getNumberByMonth(monthAd.toLowerCase());
if (monthNumber >= 10) {
return yearStr + "-" + monthNumber;
} else {
return yearStr + "-0" + monthNumber;
}
}
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
private List<Billing> TransformBilling(List<Billing> billings) {
// 已发生月份
List<String> pastMonths = getPastMonth()
// 当前月份
String monthAd = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyy-MM")).getMonth().toString().substring(0, 3).toLowerCase();

for(Billing billing : billings) {
Field[] declaredFields = ForecastingOCUnionCategoryVO.class.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
// 特殊注解属性,即十二个月份属性
if (field.getAnnotation(CalculateField.class) != null) {
String fieldName = field.getName();
// 已发生月份
if (pastMonthList.contains(fieldName)) {
field.set(billing, (Integer)field.get(billing) + 100);
} else if (fieldName.equals(monthAd)) {
// 当前月份
field.set(billing, 1);
} else {
// 未发生月份
field.set(billing, 0);
}
}
}
}
}
反射工具类
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
public class ReflectUtils {
public static Object setStringEmptyValue(Object o, Class<?> c) {
// 获取类中的所有定义字段
Field[] fields = FPAReflectUtils.getAllFields(c);
try {
// 循环遍历字段,获取字段对应的属性值
for (Field field : fields) {
// 如果不为空,设置可见性,然后返回
field.setAccessible(true);
// 属性描述器
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), c);
// 获取get方法
Method getMethod = pd.getReadMethod();
// 获取set方法
Method setMethod = pd.getWriteMethod();
Type type = getMethod.getGenericReturnType();
// 通过get方法获取到值
Object value = getMethod.invoke(o);
if (value == null && type.getTypeName().equals("java.lang.String")) {
setMethod.invoke(o, StringUtils.EMPTY);
}
}
} catch (SecurityException | IntrospectionException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
return null;
}
return o;
}

/**
* 获取本类及其父类的属性的方法,仅一个父类
*
* @param clazz 当前类对象
* @return 字段数组
*/
public static Field[] getAllFields(Class<?> clazz) {
List<Field> fieldList = new ArrayList<>(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
Field[] fields = new Field[fieldList.size()];
return fieldList.toArray(fields);
}

public static Object getValueByName(Object object, Class<?> clazz, String fieldName) throws NoSuchFieldException, IntrospectionException, InvocationTargetException, IllegalAccessException {
Field[] fields = clazz.getDeclaredFields();
if ("ID".equalsIgnoreCase(fieldName)) {
PropertyDescriptor pd = new PropertyDescriptor("id", clazz);
// 获取get方法
Method getMethod = pd.getReadMethod();
// 通过get方法获取到值
return getMethod.invoke(object);
} else {
for (Field field : fields) {
if (field.getName().equals(fieldName)) {
field.setAccessible(true);
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
// 获取get方法
Method getMethod = pd.getReadMethod();
// 通过get方法获取到值
return getMethod.invoke(object);
}
}
}
throw new NoSuchFieldException(fieldName);
}

public static Map<String, String> getAnnotationFields(Object o) {
Map<String, String> map = new HashMap<>();
Class<?> clazz = o.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
boolean annotationPresent = field.isAnnotationPresent(TableField.class);
if (annotationPresent) {
String name = field.getAnnotation(TableField.class).value();
map.put(field.getName(), name);
}
}
return map;
}

/**
* 通过表名获取字段名,ID特殊处理
*
* @param clazz
* @param tableName
* @author Kaciry
*/
public static String getFieldNameByTableName(Class<?> clazz, String tableName) throws NoSuchFieldException {
if ("ID".equalsIgnoreCase(tableName)) return "ID";
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
boolean annotationPresent = field.isAnnotationPresent(TableField.class);
if (annotationPresent) {
String fieldName = field.getAnnotation(TableField.class).value().replace("`", "");
if (fieldName.equals(tableName)) {
return field.getName();
}
}
}
throw new NoSuchFieldException();
}

/**
* 通过字段名获取表的列名
*
* @param clazz
* @param methodName
* @author Kaciry
*/
public static String getTableNameByFieldName(Class<?> clazz, String fieldName) throws NoSuchFieldException {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
boolean annotationPresent = field.isAnnotationPresent(TableField.class);
if (annotationPresent && field.getName().equals(fieldName)) {
return field.getAnnotation(TableField.class).value().replace("`", "");
}
}
throw new NoSuchFieldException();
}

/**
* map转object
*
* @param map
* @param target
* @return Object
*/
public static <T> T mapToObj(Map map, Class<T> target) throws Exception {
Field[] fields = target.getDeclaredFields();
T o = target.newInstance();
for (Field field : fields) {
Object val;
if ((val = map.get(field.getName())) != null) {
field.setAccessible(true);
field.set(o, val);
}
}
return o;
}

/**
* 目标实例化对象
*
* @param source 原对实例化象
* @param target 目标对象类
* @param sourceFields 源对象字段集合
* @param targetFields 目标对象属性字段集合
* @return 目标实例化对象
*/
private static <T> T newInstance(Object source, Class<T> target, List<Field> sourceFields,
List<Field> targetFields) throws Exception {
T t = target.newInstance();
if (targetFields.isEmpty()) {
return t;
}
for (Field field : sourceFields) {
field.setAccessible(true);
Object o = field.get(source);
Field sameField = getSameField(field, targetFields);
if (Objects.nonNull(sameField)) {
sameField.setAccessible(true);
sameField.set(t, o);
}
}
return t;
}

/**
* 获取目标对象中同源对象属性相同的属性(字段名称,字段类型一致则判定为相同)
*
* @param field 源对象属性
* @param fields 目标对象属性集合
* @return 目标对象相同的属性
*/
private static Field getSameField(Field field, List<Field> fields) {
String name = field.getName();
String type = field.getType().getName();
for (Field f : fields) {
if (name.equals(f.getName()) && type.equals(f.getType().getName())) {
return f;
}
}
return null;
}


/**
* 获取一个类中的所有属性(包括父类属性)
*
* @param c 类名
* @return List<Field>
*/
private static List<Field> getFields(Class<?> c) {
List<Field> fieldList = new ArrayList<>();
Field[] fields = c.getDeclaredFields();
if (fields.length > 0) {
fieldList.addAll(Arrays.asList(fields));
}
return getSuperClassFields(c, fieldList);
}

/**
* 递归获取父类属性
*
* @param o 类名
* @param allFields 外层定义的所有属性集合
* @return 父类所有属性
*/
private static List<Field> getSuperClassFields(Class<?> o, List<Field> allFields) {
Class<?> superclass = o.getSuperclass();
if (Objects.isNull(superclass) || Object.class.getName().equals(superclass.getName())) {
return allFields;
}
Field[] fields = superclass.getDeclaredFields();
if (fields.length == 0) {
return allFields;
}
allFields.addAll(Arrays.asList(fields));
return getSuperClassFields(superclass, allFields);
}
}

This is copyright.

...

...

00:00
00:00