人生靠反省,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
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...