人生靠反省,Java靠泛型

来源:https://www.cnblogs.com/socoool/archive/2020/04/04/12629774.html
-Advertisement-
Play Games

昨天有同事問 UserService、XxxService 都會調用 Dao 的 insert、update ... ...,這些重覆的代碼,有沒有辦法變得靈活一些? 巧了,和咱們分享的主題剛好碰上,賣個關子,先不談解決方案,就當啥事沒有發生,重新引入今天的話題(捂嘴笑)。 想蛻變的研發人員,偶爾會 ...


昨天有同事問 UserService、XxxService 都會調用 Dao 的 insert、update ... ...,這些重覆的代碼,有沒有辦法變得靈活一些?

 

巧了,和咱們分享的主題剛好碰上,賣個關子,先不談解決方案,就當啥事沒有發生,重新引入今天的話題(捂嘴笑)。

 

想蛻變的研發人員,偶爾會品味一下 Java 的源碼;久經職場的碼農,時不時也會搭建一下項目架構。其實無論你是剛入猿門,還是骨灰級戰神,今天的分享你多多少少都聽過、關註過、迷茫過甚至用過。

 

好了,準備好小板凳,讓我們一起聊聊,在你看源碼、搭架構過程中都躲避不開的 Java 中那些 E、T、?等字母都是啥意思?

 

先科普一下知識,什麼是泛型?聊啥概念,直接上代碼,直奔主題,先從 JDK 1.8 摘點源碼出來,一起與泛型打個照面,混個臉熟。

 

1. 

啥是 E?

 

E 可以說在 JDK 源碼中無處不在,咱們就從 ArrayList 的源碼進行聊起。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
    // 更多代碼 ... ...
}

  

這個 E 在此處用來創建與初始 ArrayList 的類型,其實我們可以把它換成實際的類型,舉個慄子:

 

640?wx_fmt=png

 

發現編譯器會把 E 被真正的類型所取代,其實也就是當我們創建出 ArrayList<String>,那麼對應的 add() 會變成 add(String e);當我們創建出 ArrayList<Dog>,那麼對應的 add() 會變成 add(Dog e)。

 

但是往往一不留神你會這麼寫,其實你也不想這麼寫,程式猿心裡的苦,其實說也說不清楚(捂嘴笑)。

 

640?wx_fmt=png

 

這就說明瞭為什麼寫代碼的時候,老是經常編譯不過去,老是有警告,誰讓咱定義的是 String 類型,而咱們又非要往集合中放入一條狗呢。

 

來自靈魂的拷問:只能用“E”來表示嗎?身邊同事還真問過我這個問題,在這我還是再認真的回答一次

 

其實我們可以使用任何合法的 Java 標識字元串,但是大家用單一的字母來表示,已經成為一種習慣,而 E 又代表 Element 元素的意思,所以在集合中經常用 E 來表示,但是源碼中大概率會碰到字母 T。

 

2. 

啥是T?

public static <T extends Comparable<? super T>> void sort(List<T> list) {
    list.sort(null);
}

  

上面代碼摘自 JDK 1.8 Collections 的源碼,我們發現了“T”,而且還有“?”,問號咱們暫且放一邊,著重聊一聊“T”。

 

分兩部分去看,其中第一部分 <T extends Comparable> 指的是 T 必須是 Comparable 的實現(這是重點、這是重點、這是重點);第二部分方法入參 sort(List<T> list),指的是僅能傳入繼承 Comparable 的參數化類型的 list。

 

其實也很難理解,不妨再摘個慄子配合理解。

 

640?wx_fmt=png

 

從 JDK 1.8 源碼中摘出 String 的源碼,把 String 代入 Collections 的 sort 方法,替換為 T 嘗試悟一下,看看是否 ok?!變數替換數學中大家都學過,就不深入了。

 

640?wx_fmt=png

 

但是你實際開發中,有沒有遇到過上圖的情形,在進行狗狗列表排序時,就死活報錯!報錯!!原因就是因為要排序的狗狗,必須要實現 Comparable,方能進行排序。

 

好了,T 就不再聊了,咱們還是說說這個問號吧。

 

3.

“?”問號是啥?

 

問號,看到這個估計會一臉懵逼,其實就是未知,代表一萬種可能性,在 Java 中就是萬用字元。

 

640?wx_fmt=png

 

那我們再看看上面摘自 JDK 1.8 Collections 的源碼,那麼 Comparable<? super T> 則代表 Comparable 的類型參數必須是 T 或 T 的父型,你可能有迷糊了,還是再拋點代碼吧。

 

640?wx_fmt=png

 

看到效果了沒,因為要針對狗狗排序,排序的類型必須是 Dog 或者是 Dog 的父類型,咱們傳入 String 類型,當然是編譯不通過啦,不妨改成 Dog 或者 Object 自己試一下,看看效果,在此不做演示。不過結論還是要說一下:Comparable<? super T> 則代表 Comparable 的類型參數必須是 T 或 T 的父類型。

 

提到 <? super T>,那不得不再提一提 <? extends T>,其實只要上面的搞明白了,這個也就非常清晰了,問號代表繼承和實現 T,慄子就不拋了,在框架源碼中遇到知道是啥意思就行了。

 

4.

任性的總結。

 

其實泛型是編譯期的一種檢查,能夠有效防止狗入人海,其中主要分為使用泛型的類以及使用泛型的方法;其中 E 主要用於集合的元素,除了 E 之外絕大部分是 T,然後 Java 還引入了一種萬用字元是問號,不過可以用任意 Java 有效標識符進行表示,不要再糾結、不要再糾結、不要再糾結。

 

說了這麼多,咱們開篇的問題還沒有解決啊?話不多說,直接拋代碼,不懂也沒關係,註意理解上面幾個字母就行了,下麵這段代碼分享給需要的朋友(哎呦我去,又出來個字母 D)。

@Transactional(readOnly = true)
public abstract class CrudService<D extends CrudDao<T>, T extends DataEntity<T>> extends BaseService {
   
   /**
    * 持久層對象
    */
   @Autowired
   protected D dao;
   
   /**
    * 獲取單條數據
    * @param entity
    * @return
    */
   public T get(T entity) {
      return dao.get(entity);
   }
   
   /**
    * 查詢列表數據
    * @param entity
    * @return
    */
   public List<T> findList(T entity) {
      return dao.findList(entity);
   }
   
   /**
    * 查詢分頁數據
    * @param page 分頁對象
    * @param entity
    * @return
    */
   public Page<T> findPage(Page<T> page, T entity) {
      entity.setPage(page);
      page.setList(dao.findList(entity));
      return page;
   }

   /**
    * 保存數據(插入或更新)
    * @param entity
    */
   @Transactional(readOnly = false)
   public int save(T entity) {
      if (entity.getIsNewRecord()){
         entity.preInsert();
         return dao.insert(entity);
      }else{
         entity.preUpdate();
         return dao.update(entity);
      }
   }
   
   /**
    * 刪除數據
    * @param entity
    */
   @Transactional(readOnly = false)
   public int delete(T entity) {
      return dao.delete(entity);
   }
}

 

5.

好了,今天分享就到這兒吧,希望能夠解你所惑;希望能在你前進的道路上,幫你披荊斬棘。如果感覺有點幫助,歡迎在看、秒贊,瘋狂分享轉發,因為你的每一次分享,我都認真當成了鼓勵與喜歡。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目前室內三維地圖如何輕量化,能夠在手機微信、電腦瀏覽器等平臺快速顯示地圖,顯示的地圖性能好,轉動地圖不卡是大家都要面對的問題, 使用室內三維地圖引擎ESMap後目前可以不用操心這方面的問題,開發只需要關心設備如何加到地圖上進行管理,本文章主要介紹攝像頭圖層、消防設備圖層和人員軌跡圖層進行介紹,方便大... ...
  • JavaScript 是基於面向對象和事件驅動的一門語言,事件模型是 DOM 中至關重要的內容,理解事件驅動機制、事件反饋、事件冒泡、事件捕獲以及事件委托能幫助我們更好的處理事件,寫出更優的代碼 ...
  • 01. 聊 啥 關註“一猿小講”的都知道,我們之前分享過應用架構、應用監控、日誌歸集以及程式員日常內心的那些小揪揪,幾乎成了小講、雜談的一畝三分地。 說實話,挺神奇,我也不知道每次會給大家帶來什麼驚喜。 今天的分享也不例外,你們肯定也意想不到,今天我分享的主題居然是:矛與盾,如何做好系統之盾;說人話 ...
  • 默默在看新機會的你,是不是面試的時候,偶爾被問起“能不能簡單介紹一下項目的應用系統架構”? 沉迷於業務開發的你們,有沒有考慮過“用戶訪問到你開發的業務功能,到底經過了哪些環節”? 今天我將結合這些年的一些認知理解,開壇設法給大家講一講應用系統架構的從 0 到 1。 01. 如何造一個大泥球? 產品汪 ...
  • 基本定義 裝飾者模式屬於 結構型模式 ,它可以 動態的 將新功能 附加到對象上 ,同時又 不改變其結構 。在對象功能擴展方面,它比繼承更有彈性,裝飾者模式也體現了開閉原則(OCP)。 模式結構 裝飾者和被裝飾者有 相同的超類型 ,因為裝飾者和被裝飾者必須是一樣的類型, 利用繼承是為了達到類型的匹配, ...
  • 基於觀察者模式,構建自己的一套事件分發系統。由常見的引用耦合問題,引出觀察者模式,進而利用觀察者模式的最佳實踐,事件分發系統來解決耦合問題。文章詳細解讀了事件分發系統的實現步驟,以及需要註意的一些坑。 ...
  • 1. 新建項目 IDEA中新建Maven項目,使用Maven Archetype原型:maven archetype webapp 新建項目結構為: 2. 新建包目錄 新建Java代碼目錄:src.main.java 下新建分層模型package,帶上項目的 (僅供參考) :存放全局變數,公共枚舉等 ...
  • 作為一名程式員,io知識是必不可少,其實一直在和io打交道,要麼顯示要麼隱含給了操作系統,故做下關於io的記錄。說io之前呢,先介紹什麼叫同步非同步丶阻塞非阻塞 1. 同步非同步丶阻塞非阻塞 1.1 同步是指發出一個請求,在沒有得到結果之前該請求就不返回結果,請求返回時,也就得到結果了。比如我經常用燒水 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...