摘要 調研java Class getDeclaredFields() 與getFields()的區別,設計請求參數為Javabean時,基於反射機制校驗其中非空變量的公共方法。
java Class getDeclaredFields() 與getFields()的區別
概述:
(1)getDeclaredFields() 返回Class中所有的字段,包括私有字段;
(2)getFields 只返回公共字段,即由public修飾的字段。
測試之前,請定義一個代表員工的EmployeeDTO類,成員變量訪問控制修飾符包括public等,當前,實際定義Javabean的時候,成員變量的控制修飾符是只可以為private的。
public class EmployeeDTO { public Integer id; private String sex; private String name; protected String job; // 職位 public Integer jobNumber;// 工號 private float salary; String phone; // 省略get、set方法 }
測試用例,一個main函數:
public class ValidationTest { public static void main(String[] args) { // testGetDeclaredFields(); // System.err.println(" ==================== "); // testGetFields(); validateIsEmpty(); } public static void testGetDeclaredFields() { Field[] fields = EmployeeDTO.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; System.out.println(field.getName()); } } public static void testGetFields() { 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 void validateIsEmpty() { EmployeeDTO emp = new EmployeeDTO(); emp.setId(100); emp.setJob(null); emp.setJobNumber(100001); List<String> 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源碼如下:
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; /** * @Description 校驗工具類 */ public class ValidationUtils { private final static String PIX_GET = "get"; /** * @Description 只校驗列表中傳入的字段,斷言對象中的字段值非空 * * @param object 待檢測對象 * @param checkedFieldNames 被檢查變量 * @throws Exception 如果被校驗字段的值為空,拋出此異常 */ public static void checkNotEmpty(Object object, List<String> checkedFieldNames) throws Exception { 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 = new StringBuilder(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元素 * * @return boolean,true 包含 */ private static boolean hasElement(String element, List<String> containers) { if (containers.contains(element)) { return true; } return false; } }
在main函數中調用后,控制台打印如下信息:
Non-empty field 【job】 is empty |
表明校驗成功,如果為job賦值為非空,則不再提示此信息。至於其它成員變量,同理可以測試。
所以,在校驗實際業務場景中的JavaBean的時候,就無需每次手動校驗了。丟給ValidationUtils即可,是不是很方便?