成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java反射最佳實踐

移動開發
本文的例子都可以在示例代碼中看到并下載,如果喜歡請star,如果覺得有紕漏請提交issue,如果你有更好的點子可以提交pull request。本文的示例代碼主要是基于jOOR行編寫的,如果想了解更多請查看這里的測試代碼。

本文的例子都可以在示例代碼中看到并下載,如果喜歡請star,如果覺得有紕漏請提交issue,如果你有更好的點子可以提交pull request。本文的示例代碼主要是基于jOOR行編寫的,如果想了解更多請查看這里的測試代碼。

一、需求

今天一個“懶”程序員突然跑過來說:“反射好麻煩,我要提點需求。”

聽到這句話后我就知道,今天一定不好過了,奇葩需求又來了。

我們之前寫反射都是要這么寫:


  1. public static <T> T create(HttpRequest httpRequest) { 
  2.         Object httpRequestEntity = null
  3.         try { 
  4.             Class<T> httpRequestEntityCls = (Class<T>) Class.forName(HttpProcessor.PACKAGE_NAME + "." + HttpProcessor.CLASS_NAME); 
  5.             Constructor con = httpRequestEntityCls.getConstructor(HttpRequest.class); 
  6.             httpRequestEntity = con.newInstance(httpRequest); 
  7.         } catch (ClassNotFoundException e) { 
  8.             e.printStackTrace(); 
  9.         } catch (InstantiationException e) { 
  10.             e.printStackTrace(); 
  11.         } catch (IllegalAccessException e) { 
  12.             e.printStackTrace(); 
  13.         } catch (NoSuchMethodException e) { 
  14.             e.printStackTrace(); 
  15.         } catch (InvocationTargetException e) { 
  16.             e.printStackTrace(); 
  17.         } 
  18.         return (T) httpRequestEntity; 
  19.     } 

因為反射在開發中很少用(做普通的業務開發的話),僅僅在自己寫一些框架和注解框架時會用到,所以對api總是不熟悉。每次用到api都要去網上查,查了后又得自己實驗下,很不爽。更差勁的是這樣寫法可讀性十分低下。我不希望這樣寫反射,我希望反射能像


  1. String str = new String(); 

這樣簡單,一行代碼搞定!。

此外,有很多人都說反射影響性能,在開發的時候要避免用反射。那么什么時候該用反射,什么時候不用反射呢?用什么方式來避免反射呢?如果不明白什么時候用反射,就很難將反射活學活用了。

二、分析

當我們接到上面需求后,我長舒一口氣,因為這回的需求還比較簡單。

我相信有人會說:“反射就那幾個api,一直沒變過,你就不會自己去查啊,覺得麻煩就別寫代碼啊,不知道反射的內部細節你怎么去提高呢?”
其實不然,重復寫麻煩的代碼和提高自己的代碼能力是完全無關的,我實在不知道我們寫了成千上萬行的findViewById后除了知道類要和xml文件綁定外,還學到了什么。

那么這回我們繼續來挑戰傳統思維和模板式代碼,來看看新一代的反射代碼應該怎么寫,如何用一行代碼來反射出類。
在做之前,來看看我們一般用反射來干嘛?

  1. 反射構建出無法直接訪問的類 
  2. set或get到無法訪問的類變量 
  3. 調用不可訪問的方法

三、解決方案

3.1 一行代碼寫反射

作為一個Android程序員,索性就拿TextView這個類開刀吧。首先定義一個類變量:


  1. TextView mTv; 

通過反射得到實例:


  1. // 有參數,建立類 
  2. mTv = Reflect.on(TextView.class).create(this).get(); 
  3.  
  4. // 通過類全名得到類 
  5. String word = Reflect.on("java.lang.String").create("Reflect TextView").get(); 
  6.  
  7. // 無參數,建立類 
  8. Fragment fragment = Reflect.on(Fragment.class).create().get(); 

通過反射調用方法:


  1. // 調用無參數方法 
  2. L.d("call getText() : " + Reflect.on(mTv).call("getText").toString()); 
  3.  
  4. // 調用有參數方法 
  5. Reflect.on(mTv).call("setTextColor"0xffff0000); 

通過反射get、set類變量

TextView中有個mText變量,來看看我們怎么接近它。


  1. // 設置參數 
  2. Reflect.on(mTv).set("mText""---------- new Reflect TextView ----------"); 
  3.  
  4. // 獲得參數 
  5. L.d("setgetParam is " + Reflect.on(mTv).get("mText")); 

3.2 什么時候該用反射,什么時候不用反射

又到了這樣權衡利弊的時候了,首先我們明確,在日常開發中盡量不要用反射,除非遇到了必須要通過反射才能調用的方法。比如我在做一個下拉通知中心功能的時候就遇到了這樣的情況。系統沒有提供api,所以我們只能通過反射進行調用,所以我自己寫了這樣一段代碼:

  1. <uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/> 
  2. private static void doInStatusBar(Context mContext, String methodName) { 
  3.         try { 
  4.             Object service = mContext.getSystemService("statusbar"); 
  5.             Method expand = service.getClass().getMethod(methodName); 
  6.             expand.invoke(service); 
  7.         } catch (Exception e) { 
  8.             e.printStackTrace(); 
  9.         } 
  10.     } 
  11.  
  12.     /** 
  13.      * 顯示消息中心 
  14.      */ 
  15.     public static void openStatusBar(Context mContext) { 
  16.         // 判斷系統版本號 
  17.         String methodName = (VERSION.SDK_INT <= 16) ? "expand" : "expandNotificationsPanel"
  18.         doInStatusBar(mContext, methodName); 
  19.     } 
  20.  
  21.     /** 
  22.      * 關閉消息中心 
  23.      */ 
  24.     public static void closeStatusBar(Context mContext) { 
  25.         // 判斷系統版本號 
  26.         String methodName = (VERSION.SDK_INT <= 16) ? "collapse" : "collapsePanels"
  27.         doInStatusBar(mContext, methodName); 
  28.     } 
 

先來看看利用jOOR寫的doInStatusBar方法會簡潔到什么程度:


  1. private static void doInStatusBar(Context mContext, String methodName) { 
  2.         Object service = mContext.getSystemService("statusbar"); 
  3.         Reflect.on(service).call(methodName); 
  4.     } 

哇,就一行代碼啊,很爽吧~

爽完了,我們就來看看反射問題吧。因為不是系統給出的api,所以谷歌在不同的版本上用了不同的方法名來做處理,用反射的話我們就必須進行版本的判斷,這是需要注意的,此外反射在性能方面確實不好,這里需要謹慎。

我的建議:

如果一個類中有很多地方都是private的,而你的需求都需要依賴這些方法或者變量,那么比起用反射,推薦把這個類復制出來,變成自己的類,像是toolbar這樣的類就可以進行這樣的操作。

在自己寫框架的時候,我們肯定會用到反射,很簡單的例子就是事件總線和注解框架,翔哥就說過一句話:無反射,無框架。也正因為是自己寫的框架,所以通過反射調用的方法名和參數一般不會變,更何況做運行時注解框架的話,反射肯定會出現。在這種情況下千萬不要害怕反射,索性放心大膽的做。因為它會讓你完成很多不可能完成的任務。

總結下來就是:

實際進行日常開發的時候盡量少用反射,可以通過復制原始類的形式來避免反射。在寫框架時,不避諱反射,在關鍵時利用反射來助自己一臂之力。

四、后記

我們終于完成了用一行代碼寫反射,避免了很多無意義的模板式代碼。需要再次說明的是,本文是依據jOOR 進行編寫的,這里有原項目readme的中文翻譯。

jOOR是我無意中遇到的開源庫,***次見到它時我就知道這個是我想要的,因為那時候我被反射搞的很亂,而它簡潔的編碼方式給我帶來了新的思考,大大提高了代碼可讀性。順便一說,作者人比較好(就是死活不愿意讓我放入中文的readme),技術也很不錯。該項目有很詳細的測試用例,并且還給出了幾個類似的反射調用封裝庫。可見作者在寫庫時做了大量的調研和測試工作,讓我們可以放心的運用該庫(其實就兩個類)。

本文希望帶給大家一個反射的新思路,給出一個最簡單實用的反射寫法,希望能被大家迅速運用到實踐中去。更加重要的是,通過對jOOR的分析,讓我知道了寫庫前應該調研類似的庫,而不是完全的創造新輪子,調研和測試是代碼穩定性的重要保障。

責任編輯:倪明 來源: github
相關推薦

2017-03-24 09:44:33

Java反射機制

2017-05-17 15:28:15

Java反射機制

2011-08-18 11:05:21

jQuery

2023-07-21 01:12:30

Reactfalse?變量

2024-10-10 09:46:18

2012-08-09 09:10:56

代碼審查代碼

2024-08-21 08:02:47

2014-06-09 15:50:08

2011-12-21 13:35:39

JavaJFreeChart

2014-08-19 10:06:53

IAP

2009-07-29 17:52:29

ibmdwJava

2011-12-21 13:52:27

JavaJFreeChart

2023-09-11 08:50:03

Maven工具關系管理

2023-09-13 08:00:00

JavaScript循環語句

2018-02-06 09:05:25

Java異常處理代碼

2018-01-12 14:37:34

Java代碼實踐

2018-05-10 15:06:43

Java Web分層實踐

2025-06-06 02:00:00

2025-03-19 09:04:39

2010-02-04 11:55:27

ibmdwDB2
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区中文 | 成人午夜网站 | 国产三级电影网站 | 天天夜碰日日摸日日澡 | 国产三级精品视频 | 精品一区二区三区免费毛片 | 在线观看欧美日韩视频 | 中文字幕精品一区 | 国产免费福利小视频 | 羞视频在线观看 | 国产视频久久久 | 久久国产电影 | 在线欧美小视频 | 国产成人精品一区二区三 | 欧美 日韩 中文 | 精品国产乱码久久久久久蜜臀 | av网站免费在线观看 | a毛片| 成人a网 | 国产片侵犯亲女视频播放 | 久久日本 | 精品啪啪 | 亚洲国产成人精品久久 | 天堂在线中文字幕 | 国产欧美精品一区二区色综合朱莉 | 欧美性jizz18性欧美 | 韩三级在线观看 | 91成人在线视频 | av在线播放网址 | 一区二区三区欧美在线 | 欧美1区2区 | 羞羞网站免费观看 | 亚洲人一区| 国产日韩精品在线 | 操操日 | 久久丝袜 | 亚洲成人免费视频在线 | 伊人99| 亚洲天堂男人的天堂 | 欧美一级视频免费看 | 国产精品久久久久久久久久 |