Hvordan ville en supplerende privat metode hjælpe med at undgå råtyper?
Der er en side i Oracle Docs, der forklarer, hvad "fanger et jokertegn" betyder.
I tilfælde af shuffle
, udtrækker du "dump array"-operationen til en generisk hjælpemetode:
private static <T> void dumpArray(Object[] arr, List<T> list) {
ListIterator<T> it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set((T)arr[i]);
}
}
//...
dumpArray(arr, list);
Dette virker, fordi som lægerne sagde:
Takket være hjælpemetoden bruger compileren inferens til at bestemme, at T er CAP#1, indfangningsvariablen, i invokationen.
Mens Sweeper besvarede spørgsmålet perfekt, tilføjer jeg lidt mere kontekst på raw context
advarsel, og hvad kunne have været udviklerens hensigt der (disclaimer, jeg er ikke den, der skrev den kode, jeg spekulerer bare)
Ifølge lægen,
En rå type er navnet på en generisk klasse eller grænseflade uden nogen type argumenter
Så i ovenstående kode, ListIterator it
er en rå type. Og du tildeler ListIterator
af list
som er et jokertegn type List<?>
.
Hvad kan nu være problemet i ovenstående kode ved hjælp af råtyper? Når du bruger en rå type til direkte at påkalde en generisk metode defineret i de tilsvarende generiske typer, vil compileren give en advarsel. Den vil vise en advarsel for unchecked invocation
da du omgår det generiske typetjek, og det kan forårsage en runtime fejl for type-mismatch. I dette tilfælde gør følgende det:
it.set((T)arr[i]);
Her arr[i]
er jokertegnstypen oprettet fra List<?>
men it
er en rå ListIterator
. Så ved design vil compiler vise en advarsel. For at slippe af med denne advarsel undertrykte udvikleren den ved at bruge:
@SuppressWarnings({"rawtypes", "unchecked"})
Nu ville en bedre løsning være at have en privat generisk metode til at oprette en generisk ListIterator
og dump arrayet der. Men udvikleren syntes ikke at kunne lide den idé (selvom jeg tror, det ville være renere).