Diskuze: nerozumiem tejto metode
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Zobrazeno 5 zpráv z 5.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Cílem té metody je převést obsah libovolné instance třídy podporující iterování na pole objetků. Toto pole je vráceno. Jedná se o generickou metodu, která může pracovat nad lkontejnerem uchovávajícím objekty libovolného typu (při popisu metody je tento typ zván T). Výrazem <T> v hlavicčce metody právě říkáš, že se jedná o generický typ, který bude specifikován při konkrétním volání této metody (ať už explicitně či implicitně).
Prvním parametrem je kontejner, jehož data chceš prevést do pole. Musí to být objekt implementující rozhraní Iterable nad typem odvozeným z T (což zřejmě zahrnuje i samtoné T). Druhým parametrem je v podstatě typ reprezentující T jako třídu.
Metoda přitom řeší dva případy: pokud je kontejner kolekce, získá její velikost metodou size. Pokud se o kolekci nejedná, získá počet prvků v kontejneru jeho proiterováním.
Jakmile zná počet prvků, metoda vytvoří instanci pole, naplní jej prvky ze vstupního kontejneru a vrátí jej.
V případě všech tří tebou uváděných volání dochází k automatickému odvození typu T. Pokud by se ti to nelíbilo, můžeš jej specifikovat explicitně (toArray<NazevTypu>).
Více třeba zde
https://docs.oracle.com/…methods.html
P.S.
Proč se v metodě používá objects[] a ne třeba
T[], mi je lehce záhadou (asi proto, že v Javě
neprogramuji), ale na sémantiku to nemá vliv.
To znamená, že ta metoda akceptuje cokoliv, přes co můžeš iterovat, tedy procházet jeho prvky jeden po druhém. Například zde
for (T element : list) {
se využívá faktu, že parametr list podporuje iterování. Do proměnné element se postupně vkládají jednotlivé prvky v list, dokud se nedojde na konec.
A iterování bude podporovat každá třída implementující rozhraní Iterable.
Protože generika v Javě jsou jenom syntaktický cukr. Překládají se na automatické přetypování mezi typem T a typem Object.
Tento řádek
Array.newInstance(c, size);
ve skutečnosti vrací Object, jelikož pochází z doby, kdy v Javě generika nebyla.
A nyní k tomu, co udělá použití T[] místo Object[]. Díky tomu, že za běhu generika téměř neexistují, tak jediná změna je, že se ušetří jedno přetypování proměnné result na Object[] na konci metody.
Kód poté, co ho upraví kompilátor:
public static void main(String[] args) {
List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3)});
Integer[] array = (Integer[]) toArray(list, Integer.class);
}
public static <T> T[] toArray(Iterable<? extends T> list, Class<T> c) {
int size = -1;
if(list instanceof Collection) {
Collection coll = (Collection)list;
size = coll.size();
}
if(size < 0) {
size = 0;
for(Iterator iter = list.iterator(); iter.hasNext(); ++size) {
Object o = iter.next();
}
}
Object[] result = (Object[])((Object[])Array.newInstance(c, size));
int i = 0;
Object element;
for(Iterator iter2 = list.iterator(); iter2.hasNext(); result[i++] = element) {
element = iter2.next();
}
// toto přetypování zmizí při přetypování result na T[] namísto Object[]
// na řádku s Array.newInstance
return (Object[])result;
}
Jak je vidět, tak se z metody nevrací nevrací pole generického typu, ale pole objektů a přetypování se provádí až v místě použití.
Zobrazeno 5 zpráv z 5.