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