天天看點

通過反射自動級聯執行個體化對象

通過反射級聯執行個體化對象

級聯執行個體化對象,是指對象包含其他對象執行個體的情況下執行個體化。要設定被包含對象的屬性就得對其實力化。

下面貼上代碼。

package reflection;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

interface IPerson {
    public void act();
}

interface IMessage {
    public void send();
}

class AMessage implements IMessage {
    public String aMessage;

    public AMessage() {
    }

    public String getAMessage() {
        return aMessage;
    }

    public void setAMessage(String aMessage) {
        this.aMessage = aMessage;
    }

    @Override
    public String toString() {
        return "AMessage{" +
                "aMessage='" + aMessage + '\'' +
                '}';
    }

    @Override
    public void send() {
        System.out.println("這個是A消息");
    }
}

class BMessage implements IMessage {
    public String bMessage;

    public BMessage() {
    }

    public String getBMessage() {
        return bMessage;
    }

    public void setBMessage(String bMessage) {
        this.bMessage = bMessage;
    }

    @Override
    public String toString() {
        return "BMessage{" +
                "bMessage='" + bMessage + '\'' +
                '}';
    }

    @Override
    public void send() {
        System.out.println("這是B消息");
    }
}

class Student implements IPerson {
    private String name;
    private int age;
    private AMessage aMessage;
    private BMessage bMessage;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public AMessage getAMessage() {
        return aMessage;
    }

    public void setAMessage(AMessage aMessage) {
        this.aMessage = aMessage;
    }

    public BMessage getBMessage() {
        return bMessage;
    }

    public void setBMessage(BMessage bMessage) {
        this.bMessage = bMessage;
    }

    @Override
    public String toString() {
        return "姓名:" + name + "、年紀:" + age + "、a資訊:" + aMessage + "、b資訊:" + bMessage;
    }

    @Override
    public void act() {
        System.out.println("上課");
    }
}

class Player implements IPerson {
    @Override
    public void act() {
        System.out.println("玩遊戲");
    }
}

class Factory {
    private Factory() {}
    /**
     * 反射與工廠模式的實作。實作多接口的反射實作
     *
     * @param className 具體的全限定名
     * @param clazz     clazz用來确定泛型以及泛型傳回值
     * @param <T>       傳回實體類
     * @return
     */
    public static <T> T Factor(String className, Class<T> clazz) {
        T t = null;
        try {
            t = (T) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }
    /**
     * 用來對一個類的實作自動配置成員變量,并初始化
     *
     * @param clazz
     * @param value
     * @param <T>
     * @return
     */
    public static <T> T create(Class<T> clazz, String value) {
        //clazz用來确定泛型以及泛型傳回值
        try {
            Object object = clazz.getDeclaredConstructor().newInstance();
            BeanUtils.setValue(object, value);
            return (T) object;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

class BeanUtils {//這個類實作類的反射

    private BeanUtils() { }
    public static void setValue(Object obj, String value) {
        String[] results = value.split("\\|");
        for (int i = 0; i < results.length; i++) {
            String[] attval = results[i].split(":");
            try { //這個可以避免錯誤之後的停止,繼續其他的屬性反射設定
                if (attval[0].contains(".")) {//表示需要級聯更新
                    String[] temp = attval[0].split("\\.");//temp存放冒号前面的拆分。例如:bMessage.bMessage:我是b消息拆分出來就是:1 bMessage 2bMessage
                    Object currentObject = obj;
                    for (int j = 0; j < temp.length - 1; j++) {
                        Method getMethod = currentObject.getClass().getDeclaredMethod("get" +
                                StringUtils.toUppercase(temp[j]));
                        Object tempObject = getMethod.invoke(currentObject); //擷取到目前屬性是否執行個體化
                        if (tempObject == null) {
                            Field field = currentObject.getClass().getDeclaredField(temp[j]);//擷取屬性類型
                            Method method = currentObject.getClass().getDeclaredMethod("set" +
                                    StringUtils.toUppercase(temp[j]), field.getType());
                            Object newObject = field.getType().getDeclaredConstructor().newInstance();
                            method.invoke(currentObject, newObject);//把新的對象執行個體化
                            currentObject = newObject;
                        } else {
                            currentObject = tempObject;
                        }
                    }
                    //進行屬性設定
                    Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]);//對目前屬性的設定
                    Method method = currentObject.getClass().getDeclaredMethod("set" +
                            StringUtils.toUppercase(temp[temp.length - 1]), field.getType());
                    method.invoke(currentObject, BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]));
                } else {
                    Field field = obj.getClass().getDeclaredField(attval[0]);//取得對應類型,通過類型去獲得方法
                    Object val = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
                    obj.getClass().getDeclaredMethod("set" + StringUtils.toUppercase(attval[0]), field.getType()).invoke(obj, val);//此句,獲得class-》擷取本類的方法-》鈎子函數
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 實作屬性類型轉換
     *
     * @param type  屬性類型,通過Field擷取
     * @param value 屬性類容,傳入的都是字元串,需要将其變為指定類型
     * @return 傳回轉換後的資料
     */
    private static Object convertAttributeValue(String type, String value) {
        if (null == type) {
            return null;
        }
        switch (type) {
            case "java.lang.String":
                return value;
            case "int":
                return Integer.parseInt(value);
            case "double":
                return Double.parseDouble(value);
            case "java.util.Date":
                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();
                }
            default:
                return null;
        }
    }
}

class StringUtils {
    private StringUtils() { }
    public static String toUppercase(String value) {//将首字母大寫
        if ("".equals(value) || null == value) {
            return value;
        }
        if (value.length() == 1) {
            return value.toUpperCase();
        } else {
            return value.substring(0, 1).toUpperCase() + value.substring(1, value.length());
        }
    }
}

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        String value = "name:張三|age:100|aMessage.aMessage:我是a消息|bMessage.bMessage:我是b消息";
        Student student = Factory.create(Student.class, value);
        System.out.println(student);
        System.out.println(student.getAMessage());
        System.out.println(student.getBMessage());

    }
}