Oprettelse af en generisk matrix i Java

1. Introduktion

Vi ønsker muligvis at bruge arrays som en del af klasser eller funktioner, der understøtter generics. På grund af den måde, Java håndterer generiske stoffer på, kan dette være svært.

I denne vejledning forstår vi udfordringerne ved at bruge generiske med arrays. Derefter opretter vi et eksempel på et generisk array.

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

2. Overvejelser ved brug af generiske arrays

En vigtig forskel mellem arrays og generics er, hvordan de håndhæver typekontrol. Specifikt gemmer og kontrollerer arrays typeoplysninger ved kørsel. Generiske kontrollerer dog for typefejl ved kompileringstidspunktet og har ikke typeoplysninger ved kørsel.

Java's syntaks antyder, at vi muligvis kan oprette et nyt generisk array:

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

Men hvis vi forsøgte dette, ville vi få en kompileringsfejl.

For at forstå hvorfor, lad os overveje følgende:

offentlig T [] getArray (int størrelse) {T [] genericArray = ny T [størrelse]; // antag, at dette er tilladt returnere genericArray; }

Som en ubundet generisk type T beslutter at Objekt, vores metode ved runtime vil være:

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

Så hvis vi kalder vores metode og gemmer resultatet i en Snor matrix:

Streng [] myArray = getArray (5);

Koden kompileres fint, men mislykkes ved kørsel med en ClassCastException. Dette skyldes, at vi lige har tildelt en Objekt[] til en Snor[] reference. Specifikt ville en implicit rollebesætning fra compileren ikke konvertere Objekt[] til vores krævede type Snor[].

Selvom vi ikke kan initialisere generiske arrays direkte, er det stadig muligt at opnå den tilsvarende operation, hvis den nøjagtige type information leveres af opkaldskoden.

3. Oprettelse af en generisk matrix

Lad os i vores eksempel overveje en afgrænset stakdatastruktur MyStack, hvor kapaciteten er fastgjort til en bestemt størrelse. Da vi gerne vil have stakken til at arbejde med enhver type, ville et rimeligt implementeringsvalg være et generisk array.

Lad os først oprette et felt til at gemme elementerne i vores stak, som er en generisk matrix af typen E:

private E [] -elementer;

For det andet, lad os tilføje en konstruktør:

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

Læg mærke til hvordan vi bruger java.lang.reflect.Array # newInstance for at initialisere vores generiske array, som kræver to parametre. Den første parameter specificerer typen af ​​objekt i det nye array. Den anden parameter angiver, hvor meget plads der skal oprettes til arrayet. Som et resultat af Array # newInstance er af typen Objekt, vi er nødt til at kaste det til E [] for at skabe vores generiske array.

Vi skal også bemærke konventionen om at navngive en typeparameter clazz hellere end klasse, som er et reserveret ord i Java.

4. Overvejer ArrayList

4.1. Ved brug af ArrayList i stedet for en matrix

Det er ofte lettere at bruge en generisk ArrayList i stedet for et generisk array. Lad os se, hvordan vi kan ændre os MyStack at bruge en ArrayList.

Lad os først oprette et felt til at gemme vores elementer:

private Listeelementer;

For det andet kan vi i vores stakkonstruktør initialisere ArrayList med en indledende kapacitet:

elementer = ny ArrayList (kapacitet);

Det gør vores klasse enklere, da vi ikke behøver at bruge refleksion. Vi er heller ikke forpligtet til at passere i en klasse, når vi opretter vores stack. Endelig, da vi kan indstille den indledende kapacitet for en ArrayList, kan vi få de samme fordele som en matrix.

Derfor er vi kun nødt til at konstruere matrixer med generiske stoffer i sjældne situationer, eller når vi grænseflader til et eksternt bibliotek, der kræver en matrix.

4.2. ArrayList Implementering

Interessant nok ArrayList selve er implementeret ved hjælp af generiske arrays. Lad os kigge ind ArrayList for at se hvordan.

Lad os først se listen over elementelementer:

transient Object [] elementData;

Varsel ArrayList anvendelser Objekt som elementtype. Da vores generiske type ikke er kendt før runtime, Objekt bruges som superklasse af enhver type.

Det er værd at bemærke, at næsten alle operationer i ArrayList kan bruge dette generiske array, da de ikke behøver at give et stærkt skrevet array til omverdenen, bortset fra en metode - toArray!

5. Opbygning af en matrix fra en samling

5.1. LinkedList Eksempel

Lad os se på brug af generiske arrays i Java Collections API, hvor vi bygger en ny matrix fra en samling.

Lad os først oprette en ny LinkedList med et typeargument Snor og tilføj varer til det:

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

For det andet, lad os bygge en matrix af de emner, vi lige har tilføjet:

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

For at opbygge vores array, Liste.toArray metoden kræver et input array. Det bruger denne matrix udelukkende til at få typeoplysningerne til at oprette et returarray af den rigtige type.

I vores eksempel ovenfor har vi brugt ny streng [0] som vores input array til at bygge det resulterende Snor array.

5.2. LinkedList.toArray Implementering

Lad os kigge ind LinkedList.toArray, for at se hvordan det implementeres i Java JDK.

Lad os først se på metodesignaturen:

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

For det andet, lad os se, hvordan et nyt array oprettes, når det kræves:

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

Læg mærke til, hvordan det gør brug af Array # newInstance at bygge et nyt array, som i vores stakeksempel tidligere. Bemærk også, hvordan parameter -en bruges til at give en type til Array # newInstance. Endelig er resultatet fra Array # newInstance er støbt til T [] oprette et generisk array.

6. Konklusion

I denne artikel kiggede vi først på forskellene mellem arrays og generics efterfulgt af et eksempel på oprettelse af et generisk array. Derefter viste vi, hvordan man bruger en ArrayList kan være lettere end at bruge et generisk array. Endelig så vi også på brugen af ​​et generisk array i Collections API.

Som altid er eksempelkoden tilgængelig på GitHub.


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