1. 單級屬性
針對反射和簡單Java類在實際項目中的設(shè)計意義
簡單Java類最大的特點是只進行數(shù)據(jù)的存儲 , 不對數(shù)據(jù)做復(fù)雜的操作
a. 實現(xiàn)思路
b. 代碼結(jié)構(gòu)
c. 數(shù)據(jù)類型
d. 代碼
-
主方法
import com.Dept; import com.Emp; import util.InputData; import util.reflect.ObjectInstanceFactory; public class Main { public static void main(String[] args) throws Exception { Emp emp = ObjectInstanceFactory.create(Emp.class, InputData.input()); Dept dept = ObjectInstanceFactory.create(Dept.class, InputData.inputDept()); System.out.println(emp); System.out.println(dept); } }
-
ObjectInstanceFactory
package util.reflect; import java.util.Map; public class ObjectInstanceFactory { private ObjectInstanceFactory() { } /** * 根據(jù)傳入的Class類型獲取實例化對象,同時可以將傳入的屬性進行賦值(錯誤的屬性不復(fù)制) * * @param clazz 要進行實例化的簡單java類型 * @param values 包含輸入的數(shù)據(jù) , key必須和屬性名相同 * @param <T> 帶有屬性內(nèi)容的簡答java類對象 * @return */ public static <T> T create(Class<T> clazz, Map<String, String> values) { T object = null; try { // 1. 調(diào)用無參構(gòu)造方法對類實例化 object = clazz.getDeclaredConstructor().newInstance(); // 2. 用發(fā)射處理內(nèi)容 BeanUtil.setValue(object, values); } catch (Exception e) { e.printStackTrace(); } return object; } }
-
BeanUtil
package util.reflect; import util.StringUtil; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.Map; public class BeanUtil { private BeanUtil() { } public static void setValue(Object object, Map<String, String> values) { Iterator<Map.Entry<String, String>> iterator = values.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, String> entry = iterator.next();//獲取每組數(shù)據(jù) try { // 防止某些成員輸入錯誤 Field field = object.getClass().getDeclaredField(entry.getKey()); Method method = object. getClass(). getDeclaredMethod("set" + StringUtil.initcap(entry.getKey()), field.getType()); method.invoke(object, converValue(entry.getValue(), field)); } catch (Exception e) { e.printStackTrace(); } } } /** * 實現(xiàn)字符串向指定數(shù)據(jù)類型轉(zhuǎn)換 * * @param value 接受字符串的數(shù)據(jù)內(nèi)容 * @param field 目標類型 * @return 結(jié)果 */ private static Object converValue(String value, Field field) { String fieldName = field.getType().getName(); if (String.class.getName().equalsIgnoreCase(fieldName)) { return value; } if (int.class.getName().equalsIgnoreCase(fieldName) || Integer.class.getName().equalsIgnoreCase(fieldName)) { try { return Integer.parseInt(value); } catch (Exception e) { return 0; } } if (long.class.getName().equalsIgnoreCase(fieldName) || Long.class.getName().equalsIgnoreCase(fieldName)) { try { return Long.parseLong(value); } catch (Exception e) { return 0; } } if (double.class.getName().equalsIgnoreCase(fieldName) || Double.class.getName().equalsIgnoreCase(fieldName)) { try { return Double.parseDouble(value); } catch (Exception e) { return 0; } } if (Date.class.getName().equalsIgnoreCase(fieldName)) { if (value == null || "".equalsIgnoreCase(value)) { return null; } else { SimpleDateFormat simpleDateFormat = null; if (value.matches("\\d{4}-\\d{2}-\\d{2}")) { simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) { simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } try { return simpleDateFormat.parse(value); } catch (Exception e) { return null; } } } return null; } }
-
StringUtil
package util; public class StringUtil { private StringUtil() { } public static String initcap(String name) { return name.substring(0, 1).toUpperCase() + name.substring(1); } }
-
Bean
package com; import java.util.Date; public class Emp { private String name; private int age; private Integer code; private Double sal; private Date birthday; //setter/gettter/toString方法... }
-
InputData
package util; import java.util.HashMap; import java.util.Map; public class InputData { private InputData() { } public static Map input() { Map<String, String> map = new HashMap<>(); map.put("name", "luke"); map.put("age", "28"); map.put("code", "193829"); map.put("sal", "3900.88"); map.put("birthday", "1992-05-07 08:30:01"); return map; } public static Map inputDept() { Map<String, String> map = new HashMap<>(); map.put("name", "luke"); map.put("office", "28"); return map; } }
2. 多級屬性
a. 關(guān)系圖
在一些時候也可能類中的屬性引用的其他引用類型 , 假設(shè)下列關(guān)系如下
- Emp : 雇員
- Dept : 部門
-
Company : 公司
-
- Dept : 部門
b. 代碼
所以要想完成后續(xù)的所有設(shè)計 , 那么就必須考慮當(dāng)前類對象實例化問題 , 級聯(lián)的對象必須實例化 , 在一個簡單Java類復(fù)制的過程中只能實例化一次 , 并且要有無參構(gòu)造方法
修改 : BeanUtil 的 setValue 方法
public static void setValue(Object object, Map<String, String> values) {
Iterator<Map.Entry<String, String>> iterator = values.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();//獲取每組數(shù)據(jù)
String fieldKey;
Object currentObject = object;// 設(shè)置一個當(dāng)前的操作對象(后面還會不停的修改其引用)
try {
if (entry.getKey().contains(".")) { // 如果有點則表示會出現(xiàn)級聯(lián)關(guān)系
// 依據(jù)"."進行拆分處理, 而后以此判斷, 如果發(fā)現(xiàn)getter方法調(diào)用返回的是null, 則利用setter實例化級聯(lián)對象
String[] fieldSplit = entry.getKey().split("\\."); // 特別注意這個轉(zhuǎn)義符
for (int i = 0; i < fieldSplit.length - 1; i++) { // 循環(huán)每一個屬性 不看最后一個 因為最后一個不需要實例化
// 獲取get方法
Method getMethod = currentObject.getClass().getDeclaredMethod("get" + StringUtil.initcap(fieldSplit[i]));
// 使用get犯法
Object tempReturn = getMethod.invoke(currentObject);// 獲取返回值
// 獲取到null對象
if (tempReturn == null) {//如果當(dāng)前的對象沒有被實例化,應(yīng)該調(diào)用setter設(shè)置內(nèi)容
Class<?> currentType = currentObject.getClass().getDeclaredField(fieldSplit[i]).getType();
// 獲取set方法
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initcap(fieldSplit[i]), currentType);
// 實例化該對象
tempReturn = currentType.getDeclaredConstructor().newInstance();
// 使用set方法
setMethod.invoke(currentObject, tempReturn);
}
// 切換實例化對象為當(dāng)前對象
currentObject = tempReturn;
}
// 獲取屬性名
fieldKey = entry.getKey().substring(entry.getKey().lastIndexOf(".") + 1); // 截取屬性名 ( 例如 emp.conpany.cname 最后一個cname一定是一個普通數(shù)據(jù)類型)
} else { // 如果沒有級聯(lián)屬性
// 獲取屬性名
fieldKey = entry.getKey();
}
// 獲取當(dāng)前對象需要寫入的屬性
Field field = currentObject.getClass().getDeclaredField(fieldKey);
// 獲取當(dāng)前對象需要寫入屬性的set方法
Method setethod = currentObject.getClass().getDeclaredMethod("set" + StringUtil.initcap(fieldKey), field.getType());
// 使用set方法
setethod.invoke(currentObject, converValue(entry.getValue(), field));
} catch (Exception e) {
e.printStackTrace();
}
}
}
增加 : 實體類
-
Emp
package com; import java.util.Date; public class Emp { private String name; private int age; private Integer code; private Double sal; private Date birthday; private Dept dept; //setter/gettter/toString方法... }
-
Dept
package com; public class Dept { private String name; private String office; private Company company; //setter/gettter/toString方法... }
-
Company
package com; public class Company { private String name ; private String loc; //setter/gettter/toString方法... }
修改輸入結(jié)構(gòu) : InputData
package util;
import java.util.HashMap;
import java.util.Map;
public class InputData {
private InputData() {
}
public static Map input() {
Map<String, String> map = new HashMap<>();
map.put("name", "luke");
map.put("age", "28");
map.put("code", "193829");
map.put("sal", "3900.88");
map.put("dept.office", "7樓辦公室");
map.put("dept.name", "軟件部門");
map.put("dept.company.loc", "火星98號坑");
map.put("dept.company.name", "火星研究所");
return map;
}
}
主方法運行 :
import com.Emp;
import util.InputData;
import util.reflect.ObjectInstanceFactory;
public class Main {
public static void main(String[] args) throws Exception {
Emp emp = ObjectInstanceFactory.create(Emp.class, InputData.input());
System.out.println(emp);
System.out.println(emp.getDept());
System.out.println(emp.getDept().getCompany());
}
}
運行結(jié)構(gòu) :
Emp{name='luke', age=28, code=193829, sal=3900.88, birthday=null, dept=Dept{name='軟件部門', office='7樓辦公室', company=Company{name='火星研究所', loc='火星98號坑'}}}
Dept{name='軟件部門', office='7樓辦公室', company=Company{name='火星研究所', loc='火星98號坑'}}
Company{name='火星研究所', loc='火星98號坑'}