Bevezetés a Java általános típusaiba: kovariancia és ellentmondás

Típusok

A Java egy statikusan beírt nyelv, ami azt jelenti, hogy a változó és annak típusának megadása előtt be kell jelentenie.

Például: int myInteger = 42;

Adjon meg általános típusokat.

Általános típusok

Meghatározás: „Az általános típus egy általános osztály vagy interfész, amelyet típusok felett paramétereznek.”

Lényegében az általános típusok lehetővé teszik egy általános, általános osztály (vagy módszer) megírását, amely különböző típusokkal működik, lehetővé téve a kód újrafelhasználását.

Ahelyett obj, hogy inttípusnak, Stringtípusnak vagy bármilyen más típusnak adná meg, meg kell határoznia az Boxosztályt egy típusparaméter elfogadásához <; Ezután nhasználhatja a T-t, hogy az általános típust az osztály bármely részén képviselje.

Most írja be a kovarianciát és az ellentmondást.

Kovariancia és ellentmondás

Meghatározás

A variancia arra utal, hogy a bonyolultabb típusok közötti altípus hogyan viszonyul az alkotóelemek (forrás) közötti altípushoz.

A kovariancia és az ellentmondás könnyen megjegyezhető (és rendkívül informális) meghatározása:

  • Kovariancia: fogadja el az altípusokat
  • Ellentmondás: fogadja el a típusokat

Tömbök

A Java-ban a tömbök kovariánsak , ennek 2 következménye van.

Először is, egy típusú tömb tartalmazhat típusú T[]elemeket Tés altípusait.

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

Másodszor, egy sor típus S[]egy olyan altípusa T[], ha Segy olyan altípusa T.

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

Azonban fontos megjegyezni, hogy: (1) numArregy referencia referencia típus Number[]a „tényleges tárgy” intArra „tényleges típus” Integer[].

Ezért a következő sor nagyon jól összeáll, de futási időt produkál ArrayStoreException(a kupacszennyezés miatt):

numArr[0] = 1.23; // Not ok

Futásidejű kivételt hoz létre, mert a Java futás közben tudja, hogy a „tényleges objektum” intArrvalójában egy tömb Integer.

Generikusok

Az általános típusok esetében a Java a törlés miatt nem képes futás közben megismerni a típusparaméterek típusinformációit. Ezért futás közben nem tud védekezni a halomszennyezéssel szemben.

Mint ilyen, a generikumok változatlanok.

ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Not okArrayList anotherIntArrList = intArrList; // Ok

A típusparamétereknek pontosan meg kell egyezniük a halomszennyezés elleni védelem érdekében.

De írja be a helyettesítő karaktereket.

Helyettesítő karakterek, kovariancia és ellentmondás

Helyettesítő karakterekkel a generikusok támogathatják a kovarianciát és az ellentmondást.

Az előző példát módosítva ezt kapjuk, ami működik!

ArrayList intArrList = new ArrayList();ArrayList numArrList = intArrList; // Ok

A „?” Kérdőjel helyettesítő karakterre utal, amely ismeretlen típust képvisel. Alacsonyabb korlátozású lehet, ami korlátozza az ismeretlen típust egy meghatározott típusra vagy annak szupertípusára.

Ezért a 2. sorban ? super Integer„bármilyen típus, amely egész szám vagy annak felső típusa”.

Használhatja továbbá a helyettesítő karakterek felső határát is, amelyek az ismeretlen típust meghatározott típusnak vagy altípusának korlátozzák ? extends Integer.

Csak olvasható és csak írható

A kovariancia és az ellentmondás érdekes eredményeket hoz. A kovariáns típusok csak olvashatók, míg az ellentmondásos típusok csak írhatók.

Ne feledje, hogy a kovariáns típusok elfogadják az altípusokat, tehát ArrayList er> can contain any object that is either of a Number type or its subtype.

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).

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.).

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.

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.

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 T>, while a consumer-like object that consumes objects oftype T can be of type parameter super T>.