主頁 > 資料庫 > Java自參考的通用型別

Java自參考的通用型別

2021-10-16 15:24:06 資料庫

雖然這個問題的核心已經被問過很多次了,但是有一個問題還沒有被問到(或者說我還沒有找到)。

在 Java 中,沒有辦法擁有一個參考型別本身的泛型。你可能會說 "如果你最終嘗試了,那就是你的設計有缺陷",但我反駁了。 為什么?因為java在他們自己的設計中需要它。

Object.getClass()的代碼

 /**.
     * ...
     *
     * <p><b>實際的結果型別是{@code Class<? extends |X|>}。
     * 其中{@code |X|}是擦除的靜態型別的
     *運算式,{@code getClass}被呼叫。
     * 例如,在這個代碼片段中不需要進行轉換:</p>
     *
     * <p>
     * {@code Number n = 0; }<br>
     * {@code Class<? extends Number> c = n.getClass(); }<br>
     * </p>
     * . . .
     */
    public final native Class<? > getClass()。

所以要回傳Class<? extends SELF>顯然需要SELF。這是有道理的,如果你輸入instanceOfCar.getClass(),你希望得到Class<? extends Car>

(編輯:這些問題假定不保存鑄造不是一個選項)

  • 開發者是如何做到不需要鑄造Class<? extends XYZ>的(例如,何以Class<? extends Color> c = BLACK.getClass();竟然可以編譯?
  • 他們為什么不用泛型引入一個允許自我參考的功能,因為他們自己顯然需要它?
  • 如何模擬/創建這樣一個方法?
  • class SuperClass{
        private SELF getThis(){
            return this;
        }
    }
    

    即使它看起來不像,我也知道這樣做的后果(比如使用SELF作為引數,只能在? extends SELF的情況下作業。

    uj5u.com熱心網友回復:

    他們為什么不用泛型引入一個允許自我參考的功能?

    他們為什么不用泛型引入一個允許自我參考的功能?

    因為這比乍看之下更難。例如,假設你指定 "名稱This指的是this的型別",而有人寫了如下內容:

    class Number {
        public abstract int compareTo (This other)。
    }
    
    class Integer extends Number {
        final int 值。
    
        public Integer(intvalue) {
            this.value = value。
        }
    
        @Override
        public int compareTo(this other) {
            return value - other.value。
        }
    }
    
    
    public static void main(String[] args) {
        Number n1 = new Integer42)。
        Number n2 = new Double(Math.PI)。
        n1.compareTo(n2)。
    
    

    這應該被編譯嗎?可能不會,因為類Integer提供的compareTo實作只適用于Integers,而不是Number的一些其他子型別。

    問題是,我們的規范是模糊的。當我們說"Thisthis的型別 "時,我們是指this的宣告型別(即this出現在其源代碼中的類)還是指在運行時用于創建this物件的子類?

    如果我們選擇宣告的型別,this在子類中的含義將與它的超類不同。這將是非常令人困惑的。例如:

    class Super {
        這個委托人。
    }
    
    class Sub extends Super {
        void foo() {
            delegate.foo(); //error: delegate是 "This "型別的,它沒有 "foo "方法。
        }
    }
    

    如果我們選擇運行時型別,This型別就不為呼叫者所知:

    Number x = new Integer42)。
    Number y = new Integer43);
    x.compareTo(y); // error: the method compareTo takes an argument of unknown type, but was provided a Number.
    

    也就是說,我們不能呼叫任何需要This的方法。我們甚至不能做像這樣簡單的事情:

    class Super {
        這個資料。
    }
    
    void temporarilyRemoveDataFrom(Super s) {
        Super d = s.data。
        s.data = null;
        處理(s)。
        s.data = d; //error: type Super is not assignable to an unknown subtype of Super。
    }
    

    正如你所看到的,引入對自參考型別的支持引發了參考任意型別的型別的所有問題。特別是,我們既需要型別的差異性,也需要一種方法來捕獲未知型別的值。

    因此,自參考型別并不比泛型明顯簡單。相比之下,如果我們有了泛型,那么構建自指型別是很簡單的:

    自指型別的構建是很簡單的。

    class SelfAware< T extends SelfAware<T> > {
      抽象 T getThis()。
    }
    
    class Sub extends SelfAware< Sub> {
      子getThis() {
        return this;
      }
    }
    
    SelfAware<Sub> x = new Sub() 。
    x = x.getThis(); //編譯得很好

    此外,還可以提出一個理由,即自參考型別往往被過度約束。要求程式員明確地定義型別變數和它們的邊界,可以促使他們思考哪些邊界是合適的,避免意外的過度約束。例如,java.lang.Integer并沒有實作Comparable<Integer>,而是實作了更普遍(也更有用)的Comparable<Number>

    總結來說,可子類化的自指型別并不比正常的泛型更容易使用,也不會使語言更具表現力,而且會誘使程式員過度限制型別引數,并增加語言及其工具的復雜性,但卻沒有明顯的好處。

    說了這么多,讓我們回到getClass()的奇特案例:

    開發者是如何做到不需要對getClass()的回傳值進行鑄造的?

    通過在 Java 語言規范中為該方法引入特殊處理,該規范寫道

    getClass的方法呼叫運算式的型別是Class<? extends |T|>,其中T是為getClass搜索的類或介面(§15.12.1),|T|表示擦除T(§4.6)。

    值得注意的是,即使支持自指型別,這個方法也需要特殊處理,因為它與運行時型別系統的互動使呼叫者暴露在型別清除中。

    uj5u.com熱心網友回復:

    為什么不呢

    你必須要問java 1.5的設計者,他們不會在堆疊溢位中閑逛。據我所知,他們從未被問過,或者至少從未回答過這個問題。

    但讓我們做一個有根據的猜測

    有很多原因。最主要的是,因為泛型已經足夠復雜了。實事求是地說,因為你很少需要它,所以,雖然,是的,如果foo.getClass()最終成為Class<? extends WhateverFoosTypeIs>型別的運算式就好了,但這并不重要。如果你經常遇到這種情況,那么就是你做錯的地方。你不應該使用Class,幾乎任何時候都不應該(如果你過度使用它,你可能需要寫工廠來代替),especially如果你希望.getClass()的型別是Class<? extends ThatThing>

    Java不會引入關鍵詞。至少,不是輕而易舉的。他們曾經做過一次。誠然,這是史詩級的白癡行為。引入可以想象到的最糟糕的關鍵詞:java 1.4引入了assert,這意味著整個生態系統中核心庫之外最受歡迎的方法(junit,這簡直是最受歡迎的庫,而assert很可能是它最常用的方法)不再被編譯,也不能被使用。

    因此,雖然我認為正確的回應是。引入關鍵字是次優的,但如果你必須這樣做,好吧,但不要把一個常見的方法名稱作為關鍵字引入--openjdk團隊實際上從中學到的是 "在任何情況下,永遠永遠不要引入關鍵字。- 甚至var也被引入為背景關系敏感的關鍵字(你可以在網上搜索一下;基本上,如果你使用var作為型別名或欄位名或其他什么,你的代碼在java10 中仍然有效,編譯器試圖找出你是否打算將'var'作為java10的特征或只是作為一個識別符號)。

    所以,鑒于新的關鍵字是正確的,你有什么建議?SELF不起作用 - 這已經是一個有效的識別符號了。#?Java不是Perl,也不希望把自己變成卡通式的臟話。這并不重要,不值得花一個寶貴的符號在上面。這就剩下'this'了,所以你可以做一些類似于public class Foo<S extends this> {}的事情,這將意味著Foo并沒有一個真正的typevar,但是S可以在里面用來表示'我自己的型別',并且this在任何時候都是S的型別,并且S必然是extends Foo,這可能是對java值得的一個補充。

    但是,這將是一個有點復雜和難以理解的問題(你會無意識到class Foo<F extends this>是什么意思嗎?我敢打賭,大多數java程式員將不得不去查找它,而這是一個有點奇怪的需求,這不是一個好主意)。) 你要權衡利弊(歸根結底是你需要自我打字的頻率),例如學習曲線和所有工具堆疊的負擔,以及 "燒毀 "一個功能和永久地延長已經相當大的java規范)。與其假設java lang的設計者是一群沒有考慮到這一點的白癡,不如讓我們給他們以懷疑的好處,假設他們確實意識到這是有用的,列出了一個利弊清單,并決定這不值得做。

    我真的想要這個

    你可以破解它。各種各樣的類都能做到這一點,特別是包括列舉:

    class Foo< F extends Foo<F> > { public F returnSelf() { return (F) this; /MARK } } class Bar extends Foo< Bar> { } Bar b = new Bar() 。 Bar c = b.returnSelf(); // worked

    上面的代碼是有效的,并且得到了一個 "自我參考 "的泛型。這確實意味著你在型別中引入了一個實際的typevar,這可能是你不想要的(例如,對于.getClass()方法來說,這不是一個可行的解決方案--將j.l.Object改為class Object<S extends Object<S>>會給大家帶來很大的負擔,完全不值得)。但它確實有效,而且這種 "模式 "在某種程度上是很常見的。

    注意,在標有/MARK的那一行,你會得到一個編譯器警告,你必須用@SuppressWarnings來抑制這個警告,因為這個警告是針對一個不會發生的情況而發出的。

    轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/318596.html

    標籤:

    上一篇:Kotlin中的泛型:如何實體化實作了介面的泛型類

    下一篇:從抽象的通用方法中回傳派生類的實體

    標籤雲
    其他(123570) Java(13369) Python(12731) C(7545) 區塊鏈(7372) JavaScript(7059) 基礎類(6313) AI(6244) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4120) MySQL(4012) Linux(3394) C語言(3288) C++語言(3117) Java相關(2746) 疑難問題(2699) 單片機工控(2479) Web開發(1951) 網絡通信(1793) 數據庫相關(1767) VB基礎類(1755) PHP(1727) 開發(1646) 系統維護與使用區(1617) .NETCore(1586) 基礎和管理(1579) JavaEE(1566) C++(1527) 專題技術討論區(1515) Windows客戶端使用(1484) HtmlCss(1466) ASP.NET(1428) Unity3D(1354) VCL組件開發及應用(1353) HTML(CSS)(1220) 其他技術討論專區(1200) WindowsServer(1192) .NET技术(1165) 交換及路由技術(1149) 語言基礎算法系統設計(1133) WindowsSDKAPI(1124) 界面(1088) JavaSE(1075) Qt(1074) VBA(1048) 新手樂園(1016) 其他開發語言(947) Go(907) HTML5(901) 新技術前沿(898) 硬件設計(872) 區塊鏈技術(860) 網絡編程(857) 非技術版(846) 一般軟件使用(839) 網絡協議與配置(835) Eclipse(790) Spark(750) 下載資源懸賞專區(743)

    熱門瀏覽
    • GPU虛擬機創建時間深度優化

      **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

      uj5u.com 2020-09-10 06:09:13 more
    • 可編程網卡芯片在滴滴云網路的應用實踐

      **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

      uj5u.com 2020-09-10 06:10:21 more
    • 滴滴資料通道服務演進之路

      **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

      uj5u.com 2020-09-10 06:11:05 more
    • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

      **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

      uj5u.com 2020-09-10 06:11:29 more
    • MPP (Massively Parallel Processing)大規模并行處理

      1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

      uj5u.com 2020-09-10 06:11:41 more
    • 滴滴資料倉庫指標體系建設實踐

      **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

      uj5u.com 2020-09-10 06:12:52 more
    • 單表千萬行資料庫 LIKE 搜索優化手記

      我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

      uj5u.com 2020-09-10 06:13:25 more
    • 滴滴Ceph分布式存盤系統優化之鎖優化

      **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

      uj5u.com 2020-09-10 06:14:51 more
    • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

      之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

      uj5u.com 2020-09-10 06:14:59 more
    • 爬蟲日志監控 -- Elastc Stack(ELK)部署

      傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

      uj5u.com 2020-09-10 06:15:05 more
    最新发布
    • 如何宣告一個接受任何型別方法參考的變數Function<>?

      我試圖宣告一個變數,它接受任何型別的方法參考Function<AnyObject, AnyObject or Any Enum>。
      這個方法參考將在映射器中使用,我接受一些輸入并通過呼叫另一個物件的方法來映...

      uj5u.com 2021-10-16 15:27:18 more
    • 為什么方差會對flatmapto函式產生影響?

      我想了解這個函式: 我想了解這個函式。
      public inline fun <T, R, C : MutableCollection<in R>> Array<out T>。 flatMapTo(目的地。C, transform: (T) -> Iterable<R> ): C...

      uj5u.com 2021-10-16 15:26:04 more
    • 我如何使用一個`任務<string>`實體作為方法的任務<string?>引數?

      我如何使用一個Task<string>實體作為一個方法的Task<string?>引數?
      如果我使用啟用的nullability,并且我有兩個異步方法,比如...... 如果我使用啟用的nullability,并且我有兩個...

      uj5u.com 2021-10-16 15:26:00 more
    • Webpack沒有捆綁匯入和使用的功能

      我試圖在我的函式中包含和使用BootstrapCookieConsentSettingsnpm 包bootstrap-cookie-consent-settings中的函式,initConsentBanner但 webpack 總是將其丟棄并且不包含它,即...

      uj5u.com 2021-10-16 15:25:31 more
    • 如何用Swift泛型處理成功和錯誤的API回應?

      我正試圖撰寫一個簡單的函式來處理回傳 JWT 令牌的認證 POST 請求。
      我的LoopBack 4 API將令牌作為一個JSON資料包回傳,其格式如下:
      { "token"/span>: "my. jwt.token" }

      如...

      uj5u.com 2021-10-16 15:25:24 more
    • 從抽象的通用方法中回傳派生類的實體

      我想在這里做的事情有點難以描述。我目前的需求要求我有一個可以實作介面的列舉型別。雖然不是最漂亮的解決方案,但這是我想出的辦法; )。

      我的問題本質上是,是否有任何方法來...

      uj5u.com 2021-10-16 15:24:59 more
    • Java自參考的通用型別

      雖然這個問題的核心已經被問過很多次了,但是有一個問題還沒有被問到(或者說我還沒有找到)。
      在 Java 中,沒有辦法擁有一個參考型別本身的泛型。你可能會說 "如果你最終嘗試了,那...

      uj5u.com 2021-10-16 15:24:06 more
    • Kotlin中的泛型:如何實體化實作了介面的泛型類

      我的問題是,當一個通用類實作了一個介面時,我無法將其實體化。
      實體化代碼如下;
      class MainClass {
      fun mainMethod(){
      val access = EADBAccess<AppUserModel> (Ap...

      uj5u.com 2021-10-16 15:24:00 more
    • 在CSS檔案中使用:local有什么好處?

      我一直在學習在 React 中使用 CSS 并遇到了 CSS 模塊的想法,作為其中的一部分,我遇到了這篇文章https://blog.fearcat.in/a?ID=00550-af5ece9b-eb49-4e13 -8711-26e00c48c84e...

      uj5u.com 2021-10-16 15:22:38 more
    • POST后的PHP重定向

      我正在使用谷歌登錄,并且大部分時間都在那里。用戶成功登錄,我可以訪問我的 mysql 用戶表來查找用戶記錄。在完成用戶處理并設定 $_SESSION 變數后,我想從 POST 頁面重定向回我...

      uj5u.com 2021-10-16 13:40:46 more