Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 12

Discussione: Java Generics

  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2008
    Messaggi
    813

    Java Generics

    ciao a tutti...
    ho un dubbio sulle generics di java...
    che differenza c'è nel fare:

    codice:
    class PincoPallino <? extends UnaAltraClasse> {...}
    o nel fare:
    codice:
    class PincoPallino <T extends UnaAltraClasse> {...}
    Nell'anno 1968 è bastata la potenza di due Commodore 64 per lanciare con successo una navicella sulla Luna; nell'anno 2007 ci vogliono la potenza di un processore quad core 3.30 GHz e 3 Gb di RAM (requisiti minimi ufficiali) per utilizzare Windows Vista. Qualcosa deve essere andato storto!

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Java Generics

    Originariamente inviato da Hysoka
    codice:
    class PincoPallino <? extends UnaAltraClasse> {...}
    Sbagliato sintatticamente ... non può compilare perché il "wildcard" ? non può stare lì dove l'hai messo.

    Originariamente inviato da Hysoka
    codice:
    class PincoPallino <T extends UnaAltraClasse> {...}
    Corretto. Definisce una classe generica che ha un tipo parametrico T con la restrizione che quel T, quando verrà fatta una istanziazione "concreta", sia di tipo UnaAltraClasse o suo sottotipo.

    codice:
    class PincoPallino<T extends Number> { ..... }
    
    ...
    PincoPallino<Integer> pp = new PincoPallino<Integer>();  // OK corretto: Integer è un sottotipo di Number
    
    PincoPallino<String> pp = new PincoPallino<String>();  // NO errore: String non è un sottotipo di Number
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2008
    Messaggi
    813
    è proprio questo quello che non riesco a capire...a cosa servono questi wildcards?
    Nell'anno 1968 è bastata la potenza di due Commodore 64 per lanciare con successo una navicella sulla Luna; nell'anno 2007 ci vogliono la potenza di un processore quad core 3.30 GHz e 3 Gb di RAM (requisiti minimi ufficiali) per utilizzare Windows Vista. Qualcosa deve essere andato storto!

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Hysoka
    è proprio questo quello che non riesco a capire...a cosa servono questi wildcards?
    I wildcard sono stati introdotti per offrire una specie di "polimorfismo" anche sui tipi parametrici.

    I generics sono stati implementati tramite una tecnica che si chiama "erasure" e per via di questo è stato deciso di rendere i tipi parametrici "invarianti". Un esempio per chiarire: un ArrayList<Number> non è un ArrayList<Object>!! (nonostante Number è un Object).

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    ArrayList<Object> objArr = numArr;    // NOOO, errore
    Se questa cosa fosse permessa, non avendo informazioni sul tipo parametrico a runtime ("erasure"), prova a immaginare cosa potrebbe succedere....

    Il fatto che i tipi parametrici sono invarianti ovviamente è stato visto come un limite. Ecco quindi che sono stati introdotti i wildcard (che hanno regole molto particolari e complesse).

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    ArrayList<? extends Object> objArr = numArr;    // SI
    A questo punto potresti chiederti: posso inserire un String usando objArr?? La risposta è no! Il wildcard indica: "non so di che tipo è". Con l'extends che dice: "ma sicuramente è di un tipo Object o suo sottotipo".
    Se non si sa di che tipo è, chiaramente non si può inserire nulla.

    Ora potresti chiederti a cosa serve un wildcard. Bene, l'esempio pratico e lampante è nella interfaccia Collection<E> che ha un metodo:

    boolean addAll(Collection<? extends E> c)

    Se hai una Collection<Number>, puoi aggiungere alla collezione tutti gli elementi in una Collection<Number> ma anche Collection<Integer> o Collection<Double>. Perché è logico. E con il wildcard è possibile.

    (piccola nota: complicando un pochino la dichiarazione di addAll si poteva evitare l'uso del wildcard ma con il wildcard è decisamente più chiaro e semplice).
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2008
    Messaggi
    813
    Originariamente inviato da andbin

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    ArrayList<Object> objArr = numArr;    // NOOO, errore
    Se questa cosa fosse permessa, non avendo informazioni sul tipo parametrico a runtime ("erasure"), prova a immaginare cosa potrebbe succedere....
    perdona la mia perseveranza, ma io non ci vedo niente di strano nel fare quel codice.

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    ArrayList<? extends Object> objArr = numArr;    // SI
    A questo punto potresti chiederti: posso inserire un String usando objArr?? La risposta è no! Il wildcard indica: "non so di che tipo è". Con l'extends che dice: "ma sicuramente è di un tipo Object o suo sottotipo".
    Se non si sa di che tipo è, chiaramente non si può inserire nulla.
    ma tutto quello che inserisco non lo posso usare come Object? O peggio, castarlo?
    Nell'anno 1968 è bastata la potenza di due Commodore 64 per lanciare con successo una navicella sulla Luna; nell'anno 2007 ci vogliono la potenza di un processore quad core 3.30 GHz e 3 Gb di RAM (requisiti minimi ufficiali) per utilizzare Windows Vista. Qualcosa deve essere andato storto!

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Hysoka
    perdona la mia perseveranza, ma io non ci vedo niente di strano nel fare quel codice.
    Se ... e ripeto se quella assegnazione fosse permessa allora si potrebbe inserire un String in un ArrayList<Object> che in realtà farebbe riferimento ad un ArrayList<Number>. E senza avere alcun errore/warning in compilazione!!

    E tutti questi bei discorsi sui generics e sulla type-safety andrebbero a farsi friggere!!

    Tutto il problema, a monte della proibizione di quell'assegnamento, è la "erasure". A runtime la collezione è solo un ArrayList e basta, non c'è scritto da nessuna parte (né all'interno della collezione né altrove) che è di Object o String o altro.

    E per completare la discussione c'è da dire che si possono comunque combinare casini. Sfruttando il "raw type".

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    ArrayList arr = numArr;    // OK, nessun errore
    
    arr.add("pippo");   // warning!!!
    Ma almeno il compilatore emette un warning:

    warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList

    Come a dire: "guarda che stai facendo qualcosa che probabilmente può dare problemi". E poi appunto sono affari del programmatore ....

    Originariamente inviato da Hysoka
    ma tutto quello che inserisco non lo posso usare come Object? O peggio, castarlo?
    Certo ... questo sicuramente.

    codice:
    ArrayList<Number> numArr = new ArrayList<Number>();
    // ....
    Object o = numArr.get(0);
    Ma qui non si stava parlando di cosa contengono le collezioni. Ma di come il wildcard (eventualmente con extends/super) fornisce una forma di "polimorfismo" sul tipo parametrico!!!

    Faccio un altro esempio: voglio realizzare un metodo che inserisce un certo numero di valori casuali interi in una collezione. Senza il wildcard si dovrebbe fare:

    codice:
    public static void addRandom(List<Integer> lista, int count) {
        Random r = new Random();
        while (count-- > 0) {
            lista.add(r.nextInt());
        }
    }
    È chiaramente limitato ... posso solo passare un List<Integer> (es. ArrayList<Integer> o LinkedList<Integer>). Non posso passare un ArrayList<Number> o ArrayList<Object>.
    Anche se a rigor di logica non sarebbe sbagliato (un Integer può stare benissimo in un ArrayList<Number> o ArrayList<Object>!!!).

    Con un "lower bounded" wildcard:

    codice:
    public static void addRandom(List<? super Integer> lista, int count) {
        Random r = new Random();
        while (count-- > 0) {
            lista.add(r.nextInt());
        }
    }
    Si può passare un ArrayList<Number> o ArrayList<Object>. Il 'super' indica proprio che il tipo della collezione accettato può essere Integer o un suo super-tipo.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Mar 2002
    Messaggi
    137
    ma in pratica java generics sarebbero una forma analoga ai templates di c++?
    il polimorfismo non riguarda i metodi e gli attributi nell'ereditarietà? Java non avendo le funzioni virtual e i puntatori come fa a scegliere in maniera dinamica tra un metodo o un altro
    $Pippo... la variabile preferita dall'ingegnere!

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Cosmy
    ma in pratica java generics sarebbero una forma analoga ai templates di c++?
    Concettualmente sì, anche se ovviamente la implementazione e le regole sono parecchio diverse.

    Originariamente inviato da Cosmy
    il polimorfismo non riguarda i metodi e gli attributi nell'ereditarietà? Java non avendo le funzioni virtual e i puntatori come fa a scegliere in maniera dinamica tra un metodo o un altro
    A dire il vero in Java tutte le invocazioni di metodi di istanza (salvo alcuni casi) sono "virtuali".
    Leggi qui cosa dicevo del binding statico/dinamico.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2008
    Messaggi
    813
    Vediamo se ho capito bene...se volessi fare una list (per esempio) di 'numeri', si dovrebbe fare

    ArrayList<? extends Number> al = new ArrayList<? extends Number>();

    e qui posso piazzare double, float, int, etc.? Ovviamente, usando le classi wrapper
    Nell'anno 1968 è bastata la potenza di due Commodore 64 per lanciare con successo una navicella sulla Luna; nell'anno 2007 ci vogliono la potenza di un processore quad core 3.30 GHz e 3 Gb di RAM (requisiti minimi ufficiali) per utilizzare Windows Vista. Qualcosa deve essere andato storto!

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Hysoka
    Vediamo se ho capito bene...se volessi fare una list (per esempio) di 'numeri', si dovrebbe fare

    ArrayList<? extends Number> al = new ArrayList<? extends Number>();
    No!! Innanzitutto il wildcard (bounded o unbounded che sia .. non importa) non può stare al livello "top" nella espressione della istanziazione di una classe (la parte new Blabla...).

    codice:
    ArrayList<? extends Number> al = new ArrayList<? extends Number>();    // NO
    
    ArrayList<? extends Number> al = new ArrayList<Number>();     // OK
    
    ArrayList<Vector<?>> al = new ArrayList<Vector<?>>();     // OK (il ? non è al "top" ma più interno)
    Originariamente inviato da Hysoka
    e qui posso piazzare double, float, int, etc.? Ovviamente, usando le classi wrapper
    Per chiarire bene (perché credo/deduco che non ti sia ancora completamente chiaro):

    1) Una cosa è il tipo di oggetti che si possono usare con un certo tipo parametrico.
    Esempio:
    Un ArrayList<Number> può tranquillamente contenere Integer, Double, Long, BigDecimal, ecc... Tutto ciò che è un Number.

    codice:
    ArrayList<Number> arr = new ArrayList<Number>();
    arr.add(new Integer(12));    // OK
    arr.add(new Double(20.34));  // OK

    2) Un'altra cosa è la assegnazione di un tipo parametrizzato (con una istanziazione di un tipo "concreto" es. ArrayList<String> o con una istanziazione con wildcard es. ArrayList<? extends Number>) ad un tipo più generico.
    Esempio:

    ArrayList<Number> può essere assegnato a un ArrayList<? extends Number> o a un ArrayList<? extends Object> o a un ArrayList<? super Integer>

    Perché ArrayList<Number> è un sottotipo dei 3 tipi citati sopra.

    ArrayList<? extends Integer> può essere assegnato a un ArrayList<? extends Number> o a un ArrayList<? extends Object> o a un ArrayList<?>

    Questo non vuol dire che puoi fare:
    ArrayList<? extends Number> arr = new ArrayList<? extends Integer>(); // NOOOO (spiegato all'inizio)

    Vuol dire che puoi fare ad esempio:
    ArrayList<? extends Integer> arr = new ArrayList<Integer>();
    ArrayList<? extends Number> arr2 = arr;
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.