泛型型協變逆變_Java泛型類型簡介:協變和逆變

泛型型協變逆變

by Fabian Terh

由Fabian Terh

Java泛型類型簡介:協變和逆變 (An introduction to generic types in Java: covariance and contravariance)

種類 (Types)

Java is a statically typed language, which means you must first declare a variable and its type before using it.

Java是一種靜態類型的語言,這意味著您必須先聲明一個變量及其類型,然后才能使用它。

For example: int myInteger = 42;

例如: int myInteger = 42;

Enter generic types.

輸入通用類型。

通用類型 (Generic types)

Definition: “A generic type is a generic class or interface that is parameterized over types.”

定義 :“ 泛型類型是通過類型進行參數化的泛型類或接口。”

Essentially, generic types allow you to write a general, generic class (or method) that works with different types, allowing for code re-use.

本質上,泛型類型允許您編寫可與不同類型一起使用的泛型通用類(或方法),從而可以重復使用代碼。

Rather than specifying obj to be of an int type, or a String type, or any other type, you define the Box class to accept a type parameter <;T>. Then, you can use T to represent that generic type in any part within your class.

您可以將Box類定義為接受類型參數< ; T>,而不是將obj指定為int類型, String類型或任何其他類型。 然后,CA n用t代表在類中的任何一部分泛型類型。

Now, enter covariance and contravariance.

現在,輸入協方差和自變量。

協方差和自變量 (Covariance and contravariance)

定義 (Definition)

Variance refers to how subtyping between more complex types relates to subtyping between their components (source).

差異是指更復雜類型之間的子類型如何與其組件( 源 )之間的子類型相關。

An easy-to-remember (and extremely informal) definition of covariance and contravariance is:

協方差和協方差的一個易于記憶(非常非正式)的定義是:

  • Covariance: accept subtypes

    協方差:接受子類型
  • Contravariance: accept supertypes

    矛盾:接受超類型

數組 (Arrays)

In Java, arrays are covariant, which has 2 implications.

在Java中, 數組是covariant ,有2個含義。

Firstly, an array of type T[] may contain elements of type T and its subtypes.

首先,類型為T[]的數組可以包含類型T及其子類型的元素。

Number[] nums = new Number[5];nums[0] = new Integer(1); // Oknums[1] = new Double(2.0); // Ok

Secondly, an array of type S[] is a subtype of T[] if S is a subtype of T.

其次,類型的數組S[]是的子類型T[]如果S是的子類型T

Integer[] intArr = new Integer[5];Number[] numArr = intArr; // Ok

However, it’s important to remember that: (1) numArr is a reference of reference type Number[] to the “actual object” intArr of “actual type” Integer[].

但是,重要的是要記住:(1) numArr是引用類型Number[]對“ actual type” Integer[]的“ actual object” intArr

Therefore, the following line will compile just fine, but will produce a runtime ArrayStoreException (because of heap pollution):

因此,以下行將編譯得很好,但將生成運行時ArrayStoreException (由于堆污染):

numArr[0] = 1.23; // Not ok

It produces a runtime exception, because Java knows at runtime that the “actual object” intArr is actually an array of Integer.

它產生一個運行時異常,因為Java在運行時知道“實際對象” intArr實際上是Integer的數組。

泛型 (Generics)

With generic types, Java has no way of knowing at runtime the type information of the type parameters, due to type erasure. Therefore, it cannot protect against heap pollution at runtime.

對于泛型類型,由于類型擦除,Java無法在運行時知道類型參數的類型信息。 因此,它無法在運行時防止堆污染。

As such, generics are invariant.

因此,泛型是不變的。

ArrayList<Integer> intArrList = new ArrayList<>();ArrayList<Number> numArrList = intArrList; // Not okArrayList<Integer> anotherIntArrList = intArrList; // Ok

The type parameters must match exactly, to protect against heap pollution.

類型參數必須完全匹配,以防止堆污染。

But enter wildcards.

但是輸入通配符。

通配符,協方差和逆方差 (Wildcards, covariance, and contravariance)

With wildcards, it’s possible for generics to support covariance and contravariance.

使用通配符,泛型有可能支持協方差和協方差。

Tweaking the previous example, we get this, which works!

調整前面的示例,我們得到了這個,它有效!

ArrayList<Integer> intArrList = new ArrayList<>();ArrayList<? super Integer> numArrList = intArrList; // Ok

The question mark “?” refers to a wildcard which represents an unknown type. It can be lower-bounded, which restricts the unknown type to be a specific type or its supertype.

問號“?” 表示代表未知類型的通配符。 它可以是下界的,這將未知類型限制為特定類型或其超類型。

Therefore, in line 2, ? super Integer translates to “any type that is an Integer type or its supertype”.

因此,在第2行, ? super Integer ? super Integer轉換為“任何為Integer類型或其超類型的類型”。

You could also upper-bound the wildcard, which restricts the unknown type to be a specific type or its subtype, by using ? extends Integer.

您還可以使用? extends Integer來限制通配符的范圍,通配符將未知類型限制為特定類型或其子類型? extends Integer ? extends Integer

只讀和只寫 (Read-only and write-only)

Covariance and contravariance produce some interesting outcomes. Covariant types are read-only, while contravariant types are write-only.

協方差和自變量產生一些有趣的結果。 協變類型是只讀的,而協變類型是只寫的。

Remember that covariant types accept subtypes, so ArrayList<? extends Number> can contain any object that is either of a Number type or its subtype.

還記得協變類型接受子類型ArrayList<? extends Numb ,所以ArrayList<? extends Numb ArrayList<? extends Numb ER>可以包含任何對象,或者是of a數字類型或子類型。

In this example, line 9 works, because we can be certain that whatever we get from the ArrayList can be upcasted to a Number type (because if it extends Number, by definition, it is a Number).

在此示例中,第9行有效,因為我們可以確定從ArrayList中獲得的任何內容都可以轉換為Number類型(因為如果它擴展Number ,顧名思義,它就是 Number )。

But nums.add() doesn’t work, because we cannot be sure of the “actual type” of the object. All we know is that it must be a Number or its subtypes (e.g. Integer, Double, Long, etc.).

但是nums.add()不起作用,因為我們不能確定對象的“實際類型”。 我們所知道的是它必須是一個Number或其子類型(例如Integer,Double,Long等)。

With contravariance, the converse is true.

在相反的情況下,反之亦然。

Line 9 works, because we can be certain that whatever the “actual type” of the object is, it must be Integer or its supertype, and thus accept an Integer object.

第9行行得通,因為我們可以確定,無論對象的“實際類型”是什么,它都必須是Integer或它的超類型,因此可以接受Integer對象。

But line 10 doesn’t work, because we cannot be sure that we will get an Integer. For instance, nums could be referencing an ArrayList of Objects.

但是第10行不起作用,因為我們無法確定是否會獲得Integer 。 例如, nums可以引用Objects的ArrayList。

應用領域 (Applications)

Therefore, since covariant types are read-only and contravariant types are write-only (loosely speaking), we can derive the following rule of thumb: “Producer extends, consumer super”.

因此,由于協變量類型是只讀的,而協變量類型是只寫的(松散地說),我們可以得出以下經驗法則: “生產者擴展,消費者超級”

A producer-like object that produces objects of type T can be of type parameter <? extends T>, while a consumer-like object that consumes objects of type T can be of type parameter <? super T>.

產生類型T對象的類似生產者的對象可以是參數<? extends <? extends T>,而消費類對象消費 T型可以是參數meter <? 超級T>。

翻譯自: https://www.freecodecamp.org/news/understanding-java-generic-types-covariance-and-contravariance-88f4c19763d2/

泛型型協變逆變

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393103.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393103.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393103.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安卓系統換成linux系統軟件,將舊安卓手機打造成“簡易linux”機器,并部署AdGuardHome...

從原教程的安裝Linux Deploy 完成后&#xff0c;在配置 Linux下載鏡像的一些東西時有些許出入。首先&#xff0c;我是用的下載源地址是 http://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports 清華的源挺好用的。 其他有出入的配置如圖(記得把源地址改清華的&#xff0c;華中科大…

let與expr命令的用法與實戰案例

let命令的用法 格式&#xff1a; let 賦值表達式 【注】let賦值表達式功能等同于&#xff1a;&#xff08;賦值表達式&#xff09; 例子&#xff1a;給自變量i加8 12345678[rootXCN ~]# i2 [rootXCN ~]# let ii8 [rootXCN ~]# echo $i 10[rootXCN ~]# ii8 #去掉let定義 [root…

在使用ToolBar + AppBarLayout,實現上劃隱藏Toolbar功能,遇到了一個坑。

問題&#xff1a;Android5.0以下版本Toolbar不顯示沉浸式狀態欄&#xff0c;沒有這個問題&#xff0c;但是5.0以上版本&#xff0c;就出現了莫名其妙的陰影問題&#xff0c;很是頭疼。 分享一下我的解決方案&#xff1a; 在AppBarLayout中加一個屬性&#xff1a; app:elevation…

leetcode1476. 子矩形查詢

請你實現一個類 SubrectangleQueries &#xff0c;它的構造函數的參數是一個 rows x cols 的矩形&#xff08;這里用整數矩陣表示&#xff09;&#xff0c;并支持以下兩種操作&#xff1a; updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) 用 new…

msbuild構建步驟_如何按照以下步驟構建最終的AI聊天機器人

msbuild構建步驟by Paul Pinard保羅皮納德(Paul Pinard) 如何按照以下步驟構建最終的AI聊天機器人 (How to build the ultimate AI chatbot by following these steps) 快速指南&#xff0c;可幫助您避免常見的陷阱 (A quick guide that helps you avoid common pitfalls) Bui…

第一章:最小可行區塊鏈

概覽區塊數據結構區塊哈希創世塊創建區塊保存區塊鏈驗證區塊完整性選擇最長鏈節點間通信操作節點架構運行測試小結概覽 區塊鏈的基礎概念非常簡單, 說白了就是一個維護著一個持續增長的有序數據記錄列表的這么一個分布式數據庫。在此章節中我們將實現一個簡單的玩具版的區塊鏈。…

Oracle Controlfile控制文件中記錄的信息片段sections

初學Oracle的朋友肯定對Controlfile控制文件中到底記錄了何種的信息記錄而感到好奇&#xff0c;實際上我們可以通過一個視圖v$controlfile_record_section來了解控制文件的信息片段&#xff1a; SQL> select type, record_size, records_total from v$controlfile_record_s…

linux 怎么禁止遍歷目錄,linux下遍歷目錄功能實現

/*編譯:dir:dir.cgcc -o $ $<*/#include #include #include #include #include int do_search_dir(char *path);int do_check_dir(char *fullpath, char* truefullpath);void usage(char *apps);int count 0;intmain(int argc,char **argv){char fullpath[…

leetcode面試題 16.26. 計算器(棧)

給定一個包含正整數、加()、減(-)、乘(*)、除(/)的算數表達式(括號除外)&#xff0c;計算其結果。 表達式僅包含非負整數&#xff0c;&#xff0c; - &#xff0c;*&#xff0c;/ 四種運算符和空格 。 整數除法僅保留整數部分。 示例 1: 輸入: “32*2” 輸出: 7 代碼 clas…

團隊項目電梯會議視頻

http://v.youku.com/v_show/id_XMjcyMjI3Mjk2NA.html?spma2hzp.8244740.userfeed.5!2~5~5~5!3~5~A轉載于:https://www.cnblogs.com/jingxiaopu/p/6749776.html

arduino服務器_如何使用Arduino檢查Web服務器的響應狀態

arduino服務器by Harshita Arora通過Harshita Arora 如何使用Arduino檢查Web服務器的響應狀態 (How to use Arduino to check your web server’s response status) Last year, I created Crypto Price Tracker (an app which was acquired by Redwood City Ventures this yea…

leetcode486. 預測贏家(dp)

給定一個表示分數的非負整數數組。 玩家 1 從數組任意一端拿取一個分數&#xff0c;隨后玩家 2 繼續從剩余數組任意一端拿取分數&#xff0c;然后玩家 1 拿&#xff0c;…… 。每次一個玩家只能拿取一個分數&#xff0c;分數被拿取之后不再可取。直到沒有剩余分數可取時游戲結束…

linux怎么看文件狀態,linux查看文件類型-file、狀態-stat

linux查看文件類型-file、狀態-stat首頁 計算機相關 linux命令 linux查看文件類型-file、狀態-statfile 命令可以用來查看文件類型-i mime type-s 讀取字符或塊設備文件最好指定[root192 tmp]# file freeclsfreecls: UTF-8 Unicode text[root192 tmp]# file -i freeclsfreecls:…

Linux課程筆記 Crond介紹

1. 定時任務比較及cron語法 Linux的任務調度可以分為兩類&#xff1a; 系統自身執行的任務用戶執行的工作Linux系統下另外兩種定時任務軟件&#xff1a; at&#xff1a;適合僅執行一次的調度任務&#xff0c;需要啟動一個名為atd的服務 anacron&#xff1a;這個命令主要用于非…

Python 學習日記第二篇 -- 列表,元組

一、列表 列表是一個可以包含所以數據類型的對象的位置有序集合&#xff0c;它是可以改變的。 1、列表的序列操作&#xff08;Python3&#xff09; 123456789101112131415161718192021222324>>> one_list [1,2,3,4]>>> two_list ["jonny","…

【Gamma】PhyLab 測試報告

PhyLab Gamma測試報告 測試中發現的bug Gamma階段新Bug Bug可能原因部分錯誤碼設置與原先拋異常的邏輯沖突原先代碼中使用了一些特殊的辦法處理異常Beta未發現Bug Bug可能原因控制臺新建實驗編號不能以0開頭后端處理編號會將其前導0去除&#xff0c;以數字形式存儲&#xff0c;…

如何使用Node.js,Express和MongoDB設置GraphQL服務器

by Leonardo Maldonado萊昂納多馬爾多納多(Leonardo Maldonado) 如何使用Node.js&#xff0c;Express和MongoDB設置GraphQL服務器 (How to set up a GraphQL Server using Node.js, Express & MongoDB) 從GraphQL和MongoDB開始的最直接的方法。 (The most straightforward…

leetcode954. 二倍數對數組(treemap)

給定一個長度為偶數的整數數組 A&#xff0c;只有對 A 進行重組后可以滿足 “對于每個 0 < i < len(A) / 2&#xff0c;都有 A[2 * i 1] 2 * A[2 * i]” 時&#xff0c;返回 true&#xff1b;否則&#xff0c;返回 false。 示例 1&#xff1a; 輸入&#xff1a;[3,1,…

linux文件內容打印成二進制,如何在二進制文件中只打印可打印字符(相當于Linux下的字符串)?...

在Python3中&#xff0c;以二進制模式打開文件會得到bytes的結果。迭代一個bytes對象可以得到0到255(包括0到255)的整數&#xff0c;而不是字符。從^{} documentation&#xff1a;While bytes literals and representations are based on ASCII text, bytes objects actually b…

1098 均分紙牌

1098 均分紙牌 2002年NOIP全國聯賽提高組 時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題目描述 Description有 N 堆紙牌&#xff0c;編號分別為 1&#xff0c;2&#xff0c;…, N。每堆上有若干張&#xff0c;但紙牌總數必為 N 的倍數。可以在任一堆上取若于張紙…