人生靠反省,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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...