摘要 调研java Class getDeclaredFields() 与getFields()的区别,设计请求参数为Javabean时,基于反射机制校验其中非空变量的公共方法。
java Class getDeclaredFields() 与getFields()的区别
概述:
(1)getDeclaredFields() 返回Class中所有的字段,包括私有字段;
(2)getFields 只返回公共字段,即由public修饰的字段。
测试之前,请定义一个代表员工的EmployeeDTO类,成员变量访问控制修饰符包括public等,当前,实际定义Javabean的时候,成员变量的控制修饰符是只可以为private的。
public classEmployeeDTO {publicInteger id;privateString sex;privateString name;protected String job; //职位
public Integer jobNumber;//工号
private floatsalary;
String phone;//省略get、set方法
}
测试用例,一个main函数:
public classValidationTest {public static voidmain(String[] args) {//testGetDeclaredFields();//System.err.println(" ==================== ");//testGetFields();
validateIsEmpty();
}public static voidtestGetDeclaredFields() {
Field[] fields= EmployeeDTO.class.getDeclaredFields();for (int i = 0; i < fields.length; i++) {
Field field=fields[i];
System.out.println(field.getName());
}
}public static voidtestGetFields() {
Field[] fields= EmployeeDTO.class.getFields();for (int i = 0; i < fields.length; i++) {
Field field=fields[i];
System.out.println(field.getName());
}
}
}
testGetFields ()打印结果:
id
jobNumber
testGetDeclaredFields ()打印结果:
id
sex
name
job
jobNumber
salary
phone
由测试结果可见,上述概述成立。
校验Java bean中非空字段
在ValidationTest中新增如下函数:
public static voidvalidateIsEmpty() {
EmployeeDTO emp= newEmployeeDTO();
emp.setId(100);
emp.setJob(null);
emp.setJobNumber(100001);
List checkedFieldNames = new ArrayList<>();
checkedFieldNames.add("id");
checkedFieldNames.add("job");
checkedFieldNames.add("jobNumber");try{
ValidationUtils.checkNotEmpty(emp, checkedFieldNames);
}catch(Exception e) {
System.out.println("-----------");
System.out.println(e.getMessage());
}
}
其中,本章节的主角ValidationUtils源码如下:
importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjava.util.List;/*** @Description 校验工具类*/
public classValidationUtils {private final static String PIX_GET = "get";/*** @Description 只校验列表中传入的字段,断言对象中的字段值非空
*
*@paramobject 待检测对象
*@paramcheckedFieldNames 被检查变量
*@throwsException 如果被校验字段的值为空,抛出此异常*/
public static void checkNotEmpty(Object object, List checkedFieldNames) throwsException {if (null ==object) {throw new Exception("Param is NULL");
}
Class> clazz =object.getClass();
Field[] fields=clazz.getDeclaredFields();
String fieldName= "";
StringBuilder methodName= null;
Method method= null;for(Field field : fields) {
fieldName=field.getName();if (!hasElement(fieldName, checkedFieldNames)) {continue;
}
methodName= newStringBuilder(PIX_GET);
methodName= methodName.append(fieldName.substring(0, 1).toUpperCase())
.append(fieldName.substring(1));
method=clazz.getDeclaredMethod(methodName.toString());
Object result=method.invoke(object);if (null == result || "".equals(result)) {throw new Exception("Non-empty field 【".concat(fieldName).concat("】 is empty"));
}
}
}/*** 检测container数组是否包含element元素
*
*@returnboolean,true 包含*/
private static boolean hasElement(String element, Listcontainers) {if(containers.contains(element)) {return true;
}return false;
}
}
在main函数中调用后,控制台打印如下信息:
Non-empty field 【job】 is empty
表明校验成功,如果为job赋值为非空,则不再提示此信息。至于其它成员变量,同理可以测试。
所以,在校验实际业务场景中的JavaBean的时候,就无需每次手动校验了。丢给ValidationUtils即可,是不是很方便?