反射與java簡單類

1. 單級屬性

針對反射和簡單Java類在實際項目中的設(shè)計意義

簡單Java類最大的特點是只進行數(shù)據(jù)的存儲 , 不對數(shù)據(jù)做復(fù)雜的操作

a. 實現(xiàn)思路

1563931206121.png

b. 代碼結(jié)構(gòu)

1563932264296.png

c. 數(shù)據(jù)類型

1563934325923.png

d. 代碼

1563935859137.png
  1. 主方法

    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);
        }
    }
    
    
  1. 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;
        }
    }
    
    
  1. 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;
        }
    }
    
    
  1. StringUtil

    package util;
    
    public class StringUtil {
        private StringUtil() {
        }
    
        public static String initcap(String name) {
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
    }
    
    
  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方法...
    }
    
    
  1. 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 : 公司


        1563936616641.png
1563936993946.png

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();
        }
    }
}

增加 : 實體類

  1. 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方法...
    }
    
  1. Dept

    package com;
    
    public class Dept {
        private String name;
        private String office;
        private Company company;
    
     //setter/gettter/toString方法...
    }
    
  1. 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號坑'}
1563931206121.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岗宣,一起剝皮案震驚了整個濱河市淋样,隨后出現(xiàn)的幾起案子趁猴,更是在濱河造成了極大的恐慌,老刑警劉巖娱挨,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跷坝,死亡現(xiàn)場離奇詭異柴钻,居然都是意外死亡垢粮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門占键,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捞慌,“玉大人柬批,你說我怎么就攤上這事⌒崧玻” “怎么了皮服?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵李破,是天一觀的道長。 經(jīng)常有香客問我净宵,道長,這世上最難降的妖魔是什么紧武? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任阻星,我火速辦了婚禮迫横,結(jié)果婚禮上酝碳,老公的妹妹穿的比我還像新娘疏哗。我一直安慰自己,他們只是感情好贝搁,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布雷逆。 她就那樣靜靜地躺著膀哲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仿村。 梳的紋絲不亂的頭發(fā)上兴喂,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天衣迷,我揣著相機與錄音壶谒,去河邊找鬼佃迄。 笑死贵少,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的普碎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼录平,長吁一口氣:“原來是場噩夢啊……” “哼麻车!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起斗这,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤动猬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后表箭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赁咙,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了崔拥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡凤覆,死狀恐怖链瓦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盯桦,我是刑警寧澤慈俯,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站俺附,受9級特大地震影響肥卡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜事镣,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一步鉴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧璃哟,春花似錦氛琢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至铐伴,卻和暖如春撮奏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背当宴。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工畜吊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人户矢。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓玲献,卻偏偏與公主長得像,于是被迫代替她去往敵國和親梯浪。 傳聞我的和親對象是個殘疾皇子捌年,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本文包括:1、Listener簡介2挂洛、Servlet監(jiān)聽器3礼预、監(jiān)聽三個域?qū)ο髣?chuàng)建和銷毀的事件監(jiān)聽器4、監(jiān)聽三個域?qū)?..
    廖少少閱讀 6,001評論 6 28
  • 50道經(jīng)典Java編程練習(xí)題虏劲,將數(shù)學(xué)思維運用到編程中來托酸。抱歉哈找不到文章的原貼了荠藤,有冒犯的麻煩知會聲哈~ 1.指數(shù)...
    OSET我要編程閱讀 6,947評論 0 9
  • org.springframework.beans: org.springframework.beans.fact...
    過河卒sc閱讀 583評論 1 1
  • 主要積累一些開發(fā)中比較 常用的工具類,部分借鑒于網(wǎng)絡(luò)获高,主要來源于平時開發(fā)因需求而生的小工具類 13哈肖、ArithUt...
    大鴨梨leepear閱讀 665評論 0 1
  • Java是一種可以撰寫跨平臺應(yīng)用軟件的面向?qū)ο蟮某绦蛟O(shè)計語言。Java 技術(shù)具有卓越的通用性念秧、高效性淤井、平臺移植性和...
    Java小辰閱讀 968評論 0 5