上一篇::設置多種數據類型 | 帶你學《Java語言高級特性》之九十二
【本節目標】
本節需要掌握實現級聯對象實例化以及實現對象的級聯屬性設置。
級聯對象實例化
如果現在給定的類對象中存在有其它的引用的級聯關係的情況下,稱為多級設置。例如:一個僱員屬於一個部門,一個部分屬於一個公司,所以這時對於簡單Java類的基本關係定義如下:
Company:
class Company{
private String name;
private Date createdate;
}
Dept:
class Dept{
private String dname;
private String loc;
private Company company;
}
Emp:
class Emp{
private Long empno;
private String ename;
private String job;
private double salary;
private Date hireDate;
private Dept dept;
}
如果要通過Emp進行操作,則應該使用“.”作為級聯關係的處理:
dept.dname:財務部 | Emp類實例化對象.getDept().setDname("財務部") |
---|---|
dept.company.name:MLDN | Emp類實例化對象.getDept()..getCompany().setName("MLDN") |
考慮到代碼的簡潔性,所以應該考慮可以通過級聯的配置自動實現類中屬性的實例化。
String value="empno:7369|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10" + "dept.dname:財務部|dept.company.name:MLDN";
現在的屬性存在有多級的關係,那麼對於多級的關係就必須與單級的配置區分開
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class JavaAPIDemo {
public static void main(String[] args)throws Exception{
String value="empno:7369|ename:Smith|job:Clerk|salary:750.00|hiredate:1989-10-10" + "dept.dname:財務部|dept.company.name:MLDN";
Emp emp = ClassInstanceFactory.create(Emp.class, value);
System.out.println("僱員編號:" + emp.getEmpno() + "、姓名:" + emp.getEname() + "、職位:" + emp.getJob() + "、基本工資:" + emp.getSalary() + "、受僱日期:" + emp.getHiredate());
System.out.println(emp.getDept());
System.out.println(emp.getDept().getCompany());
}
}
class ClassInstanceFactory{
private ClassInstanceFactory(){}
/**
* 實例化對象的創建方法,該對象可以根據傳入的字符串結構:"屬性:內容|屬性:內容"
* @param clazz 要進行反射實例化的Class對象,有Class就可以反射實例化對象
* @param value 要設置給對象的屬性內容
* @return 一個已經配置好屬性內容的Java對象
*/
public static <T> T create(Class<?> clazz,String value){
// 如果要想採用反射進行簡單Java類對象屬性設置的時候,類中必須要有無參構造
try {
Object obj = clazz.getDeclaredConstructor().newInstance();
BeanUtils.setValue(); //通過反射設置屬性
return (T) obj; //返回對象
}catch (Exception e) {
e.printStackTrace(); //如果此時真的出現了錯誤,本質上拋出異常也沒用
return null;
}
}
}
class StringUtils {
public static String initcap(String str) {
if (str == null || "".equals(str)) {
return str;
}
if (str.length() == 1) {
return str.toUpperCase();
}else {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
}
class BeanUtils{ //進行Bean處理的類
private BeanUtils(){}
/**
* 實現指定對象的屬性設置
* @param obj 要進行反射操作的實例化對象
* @param value 包含有指定內容的字符串,格式"屬性:內容|屬性:內容"
*/
public static void setValue(Object obj,String value){
String results [] = value.split("\\|");//按照"|"進行每一組屬性的拆分
for (int x = 0; x < results.length; x ++) { //循環設置屬性內容
//attval [0]保存的是屬性名稱,attval [1]保存的是屬性內容
String attval [] = results[x].split(":"); //獲取“屬性名稱”和內容
try {
if (attval[0].contains(".")) { //多級配置
String temp [] = attval[0].split("\\.");
Object currentObject = obj;
// 最後一位肯定是指定類中的屬性名稱,所以不在本次實例化處理的範疇之內
for (int y = 0 ; y < temp.length - 1 ; y ++) { // 實例化
// 調用了相應的getter方法,如果getter方法返回了null,表示該對象未實例化
Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
Object tempObject = getMethod.invoke(currentObject);
if (tempObject == null) { //該對象現在並沒有實例化
Field field = currentObject.getClass().getDeclaredField(temp[y]); //獲取屬性類型
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
}else {
currentObject = tempObject;
}
System.out.println(temp[y] + "--" + currentObject);
}
}else {
Field field = obj.getClass().getDeclaredField(attval[0]); //獲取成員
Method setMethod = obj.getClass().getDeclaredMethod("set" + StringUtils.initcap(attval [0]), field.getType());
Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(obj, convertValue); //調用setter方法設置內容
}
}catch (Exception e) {}
}
}
/**
* 實現屬性類型轉換處理
* @param type 屬性類型,通過Field獲取
* @param value 屬性的內容,傳入的都是字符串,需要將其變為指定類型
* @return 轉換後的數據類型
*/
private static Object convertAttributeValue(String type, String value) {
if ("long".equals(type) || "java.lang.Long".equals(type)) { //長整型
return Long.parseLong(value);
}else if ("int".equals(type) || "java.lang.int".equals(type)) {
return Integer.parseInt(value);
}else if ("double".equals(type) || "java.lang.double".equals(type)) {
return Integer.parseDouble(value);
}else if ("java.util.Date".equals(type)) {
SimpleDateFormat sdf = null;
if (value.matches("\\d{4}-\\d{2}-\\d{2}") { //日期類型
sdf = new SimpleDateFormat("yyyy-MM-dd");
} else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}") {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else {
return new Date() ; //當前日期
}
try {
return sdf.parse(value);
} catch(ParseException e) {
return new Date() ; //當前日期
}
}else {
return value;
}
}
}
class Company{
private String name;
private Date createdate;
public String getName() {
return name;
}
public void setname(String name) {
this.name = name;
}
public Date getCreatedate() {
return createdate;
}
public void setCreatedate(Date createdate) {
this.createdate = createdate;
}
}
class Dept{
private String dname;
private String loc;
private Company company;
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
class Emp{
private long empno;
private String ename;
private String job;
private double salary;
private Date hiredate;
private Dept dept;
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setJob(String job) {
this.job = job;
}
public String getEname() {
return ename;
}
public String getJob() {
return job;
}
public long getEmpno() {
return empno;
}
public void setEmpno(Long empno) {
this.empno = empno;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
}
這些自動的級聯配置的實例化處理操作,在以後進行項目的編寫之中一定會使用到。
級聯屬性設置
現在已經成功的實現級聯的對象實例化處理,那麼隨後就需要去考慮級聯的屬性的設置了,在之前考慮級聯對象實例化處理時,循環時都是少了一位的。
for (int y = 0 ; y < temp.length - 1 ; y ++) { // 實例化
// 調用了相應的getter方法,如果getter方法返回了null,表示該對象未實例化
Method getMethod = obj.getClass().getDeclaredMethod("get" + StringUtils.initcap(temp[y]));
Object tempObject = getMethod.invoke(currentObject);
if (tempObject == null) { //該對象現在並沒有實例化
Field field = currentObject.getClass().getDeclaredField(temp[y]); //獲取屬性類型
Method method = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[y]), field.getType());
Object newObject = field.getType().getDeclaredConstructor().newInstance();
method.invoke(currentObject, newObject);
currentObject = newObject;
}else {
currentObject = tempObject;
}
}
當此時代碼循環處理完成之後,currentObject表示的就是可以進行setter方法調用的對象了,並且理論上該對象一定不可能為null,隨後就可以按照我們之前的方式利用對象進行setter方法調用。
範例:實現對象的級聯屬性設置
//進行屬性內容的設置
Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]); //獲取成員
Method setMethod = currentObject.getClass().getDeclaredMethod("set" + StringUtils.initcap(temp[temp.length - 1]), field.getType());
Object convertValue = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
setMethod.invoke(currentObject, convertValue); //調用setter方法設置內容
在以後的開發中簡單Java類的賦值處理將不再重複調用setter操作完成,而這種處理形式是在正規開發中普遍採用的方式。
想學習更多的Java的課程嗎?從小白到大神,從入門到精通,更多精彩不容錯過!免費為您提供更多的學習資源。
本內容視頻來源於阿里雲大學