Szuper típusú tokenek a Java Generics-ben

1. Áttekintés

Ebben az oktatóanyagban megismerkedünk a szuper típusú tokenekkel, és megismerhetjük, hogyan segíthetnek nekünk az általános típusú információk futás közbeni megőrzésében.

2. A törlés

Néha egy adott típusú információt át kell adnunk egy módszerhez. Például itt azt várjuk, hogy Jackson a JSON bájt tömböt konvertálja a Húr:

bájt [] data = // json lekérése valahonnan String json = objectMapper.readValue (adatok, String.osztály);

Ezt az elvárást szó szerinti osztályjelen keresztül kommunikáljuk, ebben az esetben a Karakterlánc.osztály.

Ugyanakkor nem állíthatjuk be ugyanolyan elvárást az általános típusok esetében:

Map json = objectMapper.readValue (adatok, Map.class); // nem állít össze

A Java a fordítás során törli az általános típusú információkat. Ebből kifolyólag, Az általános típusú paraméterek csupán a forráskód tárgyai, és futás közben nem lesznek jelen.

2.1. Reification

Technikailag elmondható, hogy az általános típusokat a Java nem igazolja újra. A programozási nyelv terminológiájában amikor egy típus futás közben van, akkor azt mondjuk, hogy a típus újra érvényesül.

A Java újratervezett típusai a következők:

  • Egyszerű primitív típusok, mint pl hosszú
  • Nem általános absztrakciók, mint pl Húr vagy Futható
  • Nyers típusok, mint pl Lista vagy HashMap
  • Általános típusok, amelyekben minden típus nem korlátozott helyettesítő karakter, mint pl Lista vagy HashMap
  • Egyéb újrarefinált típusú tömbök, például Karakterlánc [], int [], Lista [], vagy Térkép[]

Következésképpen nem használhatunk ilyesmit Térkép.osztály mert a Térkép nem reifikált típus.

3. Szuper típusú token

Mint kiderült, kihasználhatjuk a Java névtelen belső osztályainak erejét, hogy megőrizzük a típusinformációkat a fordítási idő alatt:

public abstract class TypeReference {private final Type type; public TypeReference () {Type superclass = getClass (). getGenericSuperclass (); type = ((ParameterizedType) szuperosztály) .getActualTypeArguments () [0]; } public type getType () {return type; }}

Ez az osztály absztrakt, ezért csak alosztályokat vezethetünk le belőle.

Például létrehozhatunk egy névtelen belső:

TypeReference token = új TypeReference() {};

A kivitelező a következő lépéseket teszi a típusinformációk megőrzése érdekében:

  • Először megkapja az adott szuper osztály általános metaadatait ehhez a példányhoz - ebben az esetben a generikus szuperosztály TypeReference
  • Ezután megkapja és eltárolja az általános szuperosztály tényleges típusparaméterét - ebben az esetben az lenne Térkép

Ez a megközelítés a generikus típusú információk megőrzésére általában néven ismert szuper típusú token:

TypeReference token = új TypeReference() {}; Típus type = token.getType (); assertEquals ("java.util.Map", type.getTypeName ()); Type [] typeArguments = ((ParameterizedType) type) .getActualTypeArguments (); assertEquals ("java.lang.String", typeArguments [0] .getTypeName ()); assertEquals ("java.lang.Integer", typeArguments [1] .getTypeName ());

Szuper típusú tokenek használatával tudjuk, hogy a tárolótípus az Térkép, és típusparaméterei is Húr és Egész szám.

Ez a minta annyira híres, hogy a Jackson-könyvtáraknak és a Spring-hez hasonló keretrendszereknek saját megvalósításaik vannak. JSON objektum elemzése a Térkép úgy érhető el, hogy meghatározzuk az adott típust egy szuper típusú tokennel:

TypeReference token = új TypeReference() {}; Map json = objectMapper.readValue (adatok, token);

4. Következtetés

Ebben az oktatóanyagban megtanultuk, hogyan használhatunk szuper típusú tokeneket az általános típusú információk futás közbeni megőrzésére.

Szokás szerint az összes példa elérhető a GitHubon.