最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java反射調(diào)用get/set方法實(shí)現(xiàn)

 更新時(shí)間:2025年12月23日 09:31:25   作者:吳名氏.  
本文文章介紹了在Java中使用反射調(diào)用get/set方法時(shí),如何通過Introspector和PropertyDescriptor來更優(yōu)雅地處理,下面就來詳細(xì)的介紹一下,感興趣的可以了解一下

1 前言

最新工作中,遇到了通過反射調(diào)用get/set方法的地方,雖然反射的性能不是很好,但是相比較于硬編碼的不易擴(kuò)展,getDeclareFields可以拿到所有的成員變量,后續(xù)添加或刪除成員變量時(shí),不用修改代碼,且應(yīng)用次數(shù)只在修改數(shù)據(jù)時(shí)使用,故犧牲一些性能提高擴(kuò)展性

2 傳統(tǒng)的方式

見過很多人通過反射調(diào)用get/set方法都是通過獲取屬性的name,然后通過字符串截取將首字母大寫,再拼上get/set來做

String fieldName = field.getName();
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

也可以通過fieldName轉(zhuǎn)成字符數(shù)組,首個(gè)字符-32來避免字符串截取的

String fieldName = field.getName();
char[] chars = fieldName.toCharArray();
chars[0] = (char)(chars[0] - 32);
String getMethodName = "get" + new String(chars);

我覺得兩種方式都可以,但是不知道有沒有遇到過,生成的get/set方法并不是已get/set開頭的,而是以is開頭的,比如boolean類型的成員變量。這個(gè)時(shí)候我們就需要去判斷屬性的類型,然后用不同的前綴來拼接get/set方法名。其實(shí),在jdk中已經(jīng)包含了這樣的工具類

3 Introspector和PropertyDescriptor

關(guān)于這兩個(gè)類的詳細(xì)介紹,我這里就不說了,簡(jiǎn)單的理解就是對(duì)象信息的描述,里面提供了一些API方便我們拿到對(duì)象的信息

BeanInfo beanInfo;
try {
    beanInfo = Introspector.getBeanInfo(template.getClass());
} catch (IntrospectionException e) {
    log.info("xxxxxxxxxxxxxxxx", e);
    return null;
}

List<PropertyDescriptor> descriptors = Arrays.stream(beanInfo.getPropertyDescriptors()).filter(p -> {
    String name = p.getName();
    //過濾掉不需要修改的屬性
    return !"class".equals(name) && !"id".equals(name);
}).collect(Collectors.toList());

for (PropertyDescriptor descriptor : descriptors) {
    //descriptor.getWriteMethod()方法對(duì)應(yīng)set方法
    Method readMethod = descriptor.getReadMethod();
    System.out.println(descriptor.getName());
    try {
        Object o = readMethod.invoke(template);
        System.out.println(o);
    } catch (IllegalAccessException | InvocationTargetException e) {
        log.info("xxxxxxxxxxxxxxxx", e);
        return null;
    }
}

PropertyDescriptor類提供了getReadMethod和getWriteMethod,其實(shí)就是對(duì)于get/set方法,至于方法名稱不需要我們來關(guān)于,這樣就可以避免方法名拼錯(cuò)的情況了。 另外PropertyDescriptor除了可以通過Introspector獲取,也可以自己new來創(chuàng)建,其構(gòu)造方法還是比較全的

通常傳遞一個(gè)屬性的名稱和類對(duì)象class就可以了

List<Field> fields = Arrays.stream(template.getClass().getDeclaredFields()).filter(f -> {
    String name = f.getName();
    //過濾掉不需要修改的屬性
    return !"id".equals(name) && !"serialVersionUID".equals(name);
}).collect(Collectors.toList());

for (Field field : fields) {
    try {
        PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), template.getClass());
        Method readMethod = descriptor.getReadMethod();
        Object o = readMethod.invoke(template);
        System.out.println(o);
    } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
        e.printStackTrace();
    }
}

通過上面兩種不同的實(shí)現(xiàn)方式可以看到,Introspector會(huì)額外有一個(gè)class屬性,但是類似serialVersionUID不會(huì)算在內(nèi);而自定義PropertyDescriptor需要通過反射拿到所有的屬性,雖然不會(huì)有class屬性,但是serialVersionUID會(huì)算在內(nèi),使用的時(shí)候需要注意一下。 如果你以為這就是Introspector的全部功能,那就大錯(cuò)特錯(cuò)了。Introspector不同于普通的反射,反射一次,一段時(shí)間內(nèi)可重復(fù)使用,為什么不是永久呢,看下源碼

/**
     * Introspect on a Java Bean and learn about all its properties, exposed
     * methods, and events.
     * <p>
     * If the BeanInfo class for a Java Bean has been previously Introspected
     * then the BeanInfo class is retrieved from the BeanInfo cache.
     *
     * @param beanClass  The bean class to be analyzed.
     * @return  A BeanInfo object describing the target bean.
     * @exception IntrospectionException if an exception occurs during
     *              introspection.
     * @see #flushCaches
     * @see #flushFromCaches
     */
    public static BeanInfo getBeanInfo(Class<?> beanClass)
        throws IntrospectionException
    {
        if (!ReflectUtil.isPackageAccessible(beanClass)) {
            return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
        }
        ThreadGroupContext context = ThreadGroupContext.getContext();
        BeanInfo beanInfo;
        synchronized (declaredMethodCache) {
            beanInfo = context.getBeanInfo(beanClass);
        }
        if (beanInfo == null) {
            beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
            synchronized (declaredMethodCache) {
                context.putBeanInfo(beanClass, beanInfo);
            }
        }
        return beanInfo;
    }

注意中間加粗標(biāo)紅的代碼,這里除了同步之外,還做了一個(gè)本地的緩存

BeanInfo getBeanInfo(Class<?> type) {
    return (this.beanInfoCache != null)
            ? this.beanInfoCache.get(type)
            : null;
}

這個(gè)beanInfoCache 其實(shí)是一個(gè)WeakHashMap,每次gc被回收,所以上面說一段時(shí)間內(nèi)可以重復(fù)使用而不是永久,也是為了避免OOM吧

到此這篇關(guān)于java反射調(diào)用get/set方法實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)java反射調(diào)用get/set內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?使用注解存儲(chǔ)和讀取?Bean對(duì)象操作方法

    Spring?使用注解存儲(chǔ)和讀取?Bean對(duì)象操作方法

    在?Spring?中,要想更加簡(jiǎn)單的實(shí)現(xiàn)對(duì)?Bean?對(duì)象的儲(chǔ)存和使用,其核心就是使用?注解?,本文主要就是演示如何使用注解實(shí)現(xiàn)對(duì)?Bean?對(duì)象的存取操作,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • 詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用

    詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用

    這篇文章主要介紹了詳解Spring緩存注解@Cacheable,@CachePut , @CacheEvict使用,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-05-05
  • Java多線程之線程安全問題詳解

    Java多線程之線程安全問題詳解

    Java中的多線程編程是指使用Java語言創(chuàng)建和控制線程的能力,這篇文章主要介紹了Java多線程之線程安全問題的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-11-11
  • Java實(shí)現(xiàn)讀取文件夾下(包括子目錄)所有文件的文件名

    Java實(shí)現(xiàn)讀取文件夾下(包括子目錄)所有文件的文件名

    這篇文章主要介紹了Java實(shí)現(xiàn)讀取文件夾下(包括子目錄)所有文件的文件名,本文把代碼組織成了一個(gè)模塊,可以很方便的使用,需要的朋友可以參考下
    2015-06-06
  • springboot-mongodb的多數(shù)據(jù)源配置的方法步驟

    springboot-mongodb的多數(shù)據(jù)源配置的方法步驟

    這篇文章主要介紹了springboot-mongodb的多數(shù)據(jù)源配置的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • MyBatis帶參查詢的方法詳解

    MyBatis帶參查詢的方法詳解

    這篇文章主要介紹了MyBatis帶參查詢的方法詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 淺談SpringCloud feign的http請(qǐng)求組件優(yōu)化方案

    淺談SpringCloud feign的http請(qǐng)求組件優(yōu)化方案

    這篇文章主要介紹了淺談SpringCloud feign的http請(qǐng)求組件優(yōu)化方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • 從零開始學(xué)SpringBoot如何開始使用圖文詳解

    從零開始學(xué)SpringBoot如何開始使用圖文詳解

    這篇文章主要介紹了從零開始學(xué)SpringBoot如何開始使用,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • JUC并發(fā)編程LinkedBlockingQueue隊(duì)列深入分析源碼

    JUC并發(fā)編程LinkedBlockingQueue隊(duì)列深入分析源碼

    LinkedBlockingQueue 是一個(gè)可選有界阻塞隊(duì)列,這篇文章主要為大家詳細(xì)介紹了Java中LinkedBlockingQueue的實(shí)現(xiàn)原理與適用場(chǎng)景,感興趣的可以了解一下
    2023-04-04
  • springmvc+kindeditor文件上傳實(shí)例詳解

    springmvc+kindeditor文件上傳實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了springmvc+kindeditor文件上傳實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08

最新評(píng)論

陵川县| 威信县| 敖汉旗| 永善县| 福州市| 保德县| 惠州市| 比如县| 兴宁市| 安西县| 南岸区| 自贡市| 宝清县| 邹平县| 濉溪县| 德惠市| 泸溪县| 邯郸市| 雅安市| 会理县| 阳西县| 吉木乃县| 沙田区| 冀州市| 芜湖县| 祁东县| 临潭县| 垣曲县| 简阳市| 高密市| 建湖县| 五大连池市| 仁化县| 吴桥县| 喀喇| 吉木萨尔县| 彝良县| 武义县| 新安县| 镇宁| 临邑县|