Opprette en generisk matrise i Java

1. Introduksjon

Det kan være lurt å bruke matriser som en del av klasser eller funksjoner som støtter generiske legemidler. På grunn av måten Java håndterer generiske stoffer på, kan dette være vanskelig.

I denne opplæringen vil vi forstå utfordringene ved å bruke generiske legemidler med matriser. Deretter lager vi et eksempel på en generisk matrise.

Vi vil også se på hvor Java API har løst et lignende problem.

2. Hensyn når du bruker generiske matriser

En viktig forskjell mellom matriser og generiske stoffer er hvordan de håndhever typekontroll. Spesielt arrays lagrer og sjekker typeinformasjon ved kjøretid. Generiske, men sjekk for typefeil ved kompileringstid og har ikke typeinformasjon ved kjøretid.

Java syntaks antyder at vi kanskje kan lage en ny generisk matrise:

T [] elementer = ny T [størrelse];

Men hvis vi prøvde dette, ville vi få en kompileringsfeil.

For å forstå hvorfor, la oss vurdere følgende:

offentlig T [] getArray (int størrelse) {T [] genericArray = ny T [størrelse]; // antar at dette er tillatt retur genericArray; }

Som en ubundet generisk type T løser å Gjenstand, vår metode ved kjøretid vil være:

public Object [] getArray (int size) {Object [] genericArray = new Object [size]; returner generiskArray; }

Så hvis vi kaller metoden vår og lagrer resultatet i en String matrise:

Streng [] myArray = getArray (5);

Koden vil kompilere fint, men mislykkes i løpetid med en ClassCastException. Dette er fordi vi nettopp har tildelt en Gjenstand[] til en Streng [] henvisning. Spesielt vil en implisitt rollebesetning av kompilatoren ikke konvertere Gjenstand[] til ønsket type Streng [].

Selv om vi ikke kan initialisere generiske matriser direkte, er det fortsatt mulig å oppnå den tilsvarende operasjonen hvis den nøyaktige typen informasjon er gitt av ringekoden.

3. Lage en generisk matrise

For eksempel, la oss vurdere en begrenset stabeldatastruktur MyStack, hvor kapasiteten er festet til en viss størrelse. Ettersom vi ønsker at stabelen skal fungere med alle typer, vil et rimelig implementeringsvalg være et generisk utvalg.

Først, la oss lage et felt for å lagre elementene i stakken vår, som er et generisk utvalg av typen E:

private E [] -elementer;

For det andre, la oss legge til en konstruktør:

public MyStack (Class clazz, int capacity) {elements = (E []) Array.newInstance (clazz, capacity); }

Legg merke til hvordan vi bruker java.lang.reflect.Array # newInstance for å initialisere vårt generiske utvalg, som krever to parametere. Den første parameteren spesifiserer objekttypen i den nye matrisen. Den andre parameteren spesifiserer hvor mye plass som skal opprettes for matrisen. Som et resultat av Array # newInstance er av typen Gjenstand, vi må kaste den til E [] for å lage vårt generiske utvalg.

Vi bør også merke oss konvensjonen om å navngi en typeparameter clazz heller enn klasse, som er et reservert ord i Java.

4. Vurderer ArrayList

4.1. Ved hjelp av ArrayList i stedet for en matrise

Det er ofte lettere å bruke en generisk ArrayList i stedet for et generisk utvalg. La oss se hvordan vi kan endre oss MyStack å bruke en ArrayList.

La oss først lage et felt for å lagre elementene våre:

private Listeelementer;

For det andre, i stakkkonstruktøren vår, kan vi initialisere ArrayList med en innledende kapasitet:

elementer = ny ArrayList (kapasitet);

Det gjør klassen vår enklere, ettersom vi ikke trenger å bruke refleksjon. Vi er heller ikke pålagt å passere i en klasse bokstavelig når vi lager stakken vår. Til slutt, da vi kan angi startkapasiteten til en ArrayList, kan vi få de samme fordelene som en matrise.

Derfor trenger vi bare å konstruere matriser av generiske stoffer i sjeldne situasjoner, eller når vi grensesnitt med noe eksternt bibliotek som krever en matrise.

4.2. ArrayList Gjennomføring

Interessant, ArrayList selve er implementert ved hjelp av generiske matriser. La oss titte inn ArrayList for å se hvordan.

La oss først se feltelementelisten:

transient Object [] elementData;

Legge merke til ArrayList bruker Gjenstand som elementtype. Siden vår generiske type ikke er kjent før kjøretid, Gjenstand brukes som superklasse av enhver type.

Det er verdt å merke seg at nesten alle operasjoner i ArrayList kan bruke denne generiske matrisen ettersom de ikke trenger å gi en sterkt skrevet matrice til omverdenen, bortsett fra en metode - toArray!

5. Bygg en serie fra en samling

5.1. LinkedList Eksempel

La oss se på bruk av generiske matriser i Java Collections API, hvor vi bygger en ny matrise fra en samling.

La oss først lage en ny LinkedList med et typeargument String og legg til ting i den:

Listeelementer = ny LinkedList (); items.add ("første vare"); items.add ("andre element"); 

For det andre, la oss bygge en rekke elementer som vi nettopp har lagt til:

Streng [] itemsAsArray = items.toArray (ny streng [0]);

For å bygge vårt utvalg, Liste.toArray metoden krever et inngangssett. Den bruker denne matrisen utelukkende for å få typeinformasjonen til å lage en returmatrise av riktig type.

I eksemplet vårt ovenfor har vi brukt ny streng [0] som vårt input-array for å bygge det resulterende String array.

5.2. LinkedList.toArray Gjennomføring

La oss ta en titt innover LinkedList.toArray, for å se hvordan den implementeres i Java JDK.

La oss først se på metodesignaturen:

offentlig T [] til Array (T [] a)

For det andre, la oss se hvordan en ny matrise opprettes når det er nødvendig:

a = (T []) java.lang.reflect.Array.newInstance (a.getClass (). getComponentType (), size);

Legg merke til hvordan den bruker Array # newInstance å bygge en ny matrise, som i vårt stackeksempel tidligere. Legg også merke til hvordan parameter en brukes til å gi en type til Array # newInstance. Endelig er resultatet fra Array # newInstance er kastet til T [] lage en generisk matrise.

6. Konklusjon

I denne artikkelen så vi først på forskjellene mellom matriser og generiske stoffer, etterfulgt av et eksempel på å lage en generisk matrise. Så viste vi hvordan vi bruker en ArrayList kan være enklere enn å bruke en generisk matrise. Til slutt så vi også på bruken av en generisk matrise i Collections API.

Som alltid er eksempelkoden tilgjengelig på GitHub.


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