Super typy tokenov v generike Java

1. Prehľad

V tomto tutoriáli sa oboznámime s tokenmi super typu a uvidíme, ako nám môžu pomôcť zachovať informácie generického typu za behu.

2. Vymazanie

Niekedy musíme metóde sprostredkovať informácie o konkrétnom type. Napríklad tu očakávame od Jacksona, že prevedie bajtové pole JSON na a Reťazec:

byte [] data = // načítať json odkiaľkoľvek String json = objectMapper.readValue (data, String.class);

Komunikujeme o tomto očakávaní prostredníctvom doslova tokenu triedy, v tomto prípade Reťazec.trieda.

Nemôžeme však rovnako ľahko nastaviť rovnaké očakávania pre generické typy:

Mapa json = objectMapper.readValue (data, Map.class); // nebude kompilovaný

Java počas kompilácie vymaže informácie o všeobecnom type. Preto parametre generického typu sú iba artefaktom zdrojového kódu a budú za behu chýbať.

2.1. Znovuzjednotenie

Technicky vzaté, generické typy nie sú v Jave overené. V terminológii programovacieho jazyka keď je typ prítomný za behu, hovoríme, že je typ zjednotený.

Zjednotené typy v prostredí Java sú nasledujúce:

  • Jednoduché primitívne typy ako napr dlho
  • Negenerické abstrakcie ako napr String alebo Spustiteľné
  • Surové druhy ako napr Zoznam alebo HashMap
  • Generické typy, v ktorých sú všetky typy neviazané zástupné znaky, ako napr Zoznam alebo HashMap
  • Polia ďalších reifikovaných typov, ako napr Reťazec [], int [], zoznam [], alebo Mapa []

V dôsledku toho nemôžeme použiť niečo podobné Mapa.trieda pretože Mapa nie je reifikovaný typ.

3. Token super typu

Ako sa ukazuje, môžeme využiť silu anonymných vnútorných tried v Jave na zachovanie informácií o type počas kompilácie:

verejná abstraktná trieda TypeReference {súkromná konečná Typ typu; public TypeReference () {Type superclass = getClass (). getGenericSuperclass (); typ = ((ParameterizedType) nadtrieda) .getActualTypeArgumenty () [0]; } public Type getType () {návratový typ; }}

Táto trieda je abstraktná, takže z nej môžeme odvodiť iba podtriedy.

Napríklad môžeme vytvoriť anonymný vnútorný:

TypeReference token = nový TypeReference() {};

Konštruktor vykoná nasledujúce kroky na zachovanie informácií o type:

  • Najprv získa metadáta generickej nadtriedy pre tento konkrétny prípad - v tomto prípade je generická nadtrieda TypeReference
  • Potom získa a uloží parameter aktuálneho typu pre generickú nadtriedu - v takom prípade by to bolo Mapa

Tento prístup na uchovanie informácií o všeobecnom type je zvyčajne známy ako token super typu:

TypeReference token = nový TypeReference() {}; Typ 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 ());

Použitím tokenov super typu vieme, že typ kontajnera je Mapa, a tiež jeho parametre typu String a Celé číslo.

Tento model je taký slávny, že knižnice ako Jackson a rámce ako Spring majú jeho vlastnú implementáciu. Analýza objektu JSON do a Mapa je možné dosiahnuť definovaním tohto typu pomocou tokenu super typu:

TypeReference token = nový TypeReference() {}; Mapa json = objectMapper.readValue (údaje, token);

4. Záver

V tomto tutoriáli sme sa naučili, ako môžeme použiť tokeny super typu na zachovanie informácií o všeobecnom type za behu.

Ako obvykle sú všetky príklady dostupné na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found