Richiesta di aiuto per capire questo metodo :

di il
16 risposte

Richiesta di aiuto per capire questo metodo :

Buongiorno.

Sto' approfondendo un po' lo studio di java e ogni tanto incontro qualche difficoltaà nel capire alcuni metodi per esempio non capisco alcune cose descritte nelle parentesi tonde di questo metodo .
Non capisco i punti interrogativi , capisco le parentesi di parametrizzazione e non capisco la m finale .
Capisco che essendo una mappa K sta' per chiave e V per valore .
Credo che il significato di putAll voglia dire letteralmente " inserisci tutte le chiavi e tutti i valori "

void putAll(Map <? extends K ,? extends V > m)

Credo che con questo codice vengano inizialmente create due mappe map e map2 e inseriti dei valori con delle chiavi e poi viene invocato il metodo
map.putAll(null,null) e map.putAll(man2) che non ho ben capito la loro funzione .

Ricapitolando :

La cosa che vorrei sapere non soltanto per questo metodo ma anche per gli'altri metodi simili e' come decifrare la dicitura tra le parentesi tonde (Map<? extends K , ? extends V > m)

Perché in questo metodo viene messo :

Il punto interrogativo ?
extends
e la lettera m .

...Grazie per l'aiuto .



CODICE:

import java.util.HashMap;
import java.util.Map;

public class Main {
public static void main(String[] a) {
Map<String,String> map = new HashMap<String,String>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put(null, null);

Map<String,String> map2 = new HashMap<String,String>();
map2.put("key4", "value4");
map2.put("key5", "value5");
map2.put("key6", "value6");
map.putAll(map2);

System.out.println(map);
}
}

16 Risposte

  • Re: Richiesta di aiuto per capire questo metodo :

    FabioJ ha scritto:


    Credo che il significato di putAll voglia dire letteralmente " inserisci tutte le chiavi e tutti i valori "
    Sì.

    map1.putAll(map2);

    vuol dire: aggiungi(/sovrascrivi) in map1 tutte le associazioni contenute in map2

    FabioJ ha scritto:


    Non capisco i punti interrogativi , capisco le parentesi di parametrizzazione e non capisco la m finale .
    Il punto interrogativo ?
    extends
    e la lettera m .
    Se hai una Map<Number,Object> puoi aggiungerci con putAll tutte le entry presenti in un Map<Integer,String> o un Map<Long,Date> perché tutti i valori in queste ultime due mappe sono leciti per essere contenuti in un Map<Number,Object>.

    Se non ci fossero i ? extends, allora potresti aggiungere SOLO un'altra Map<Number,Object>, che sarebbe molto più limitante.

    Ti serve capire:
    - perché i generics di base sono "invarianti".
    - perché sono stati introdotti i "bound" tramite extends/super (co-varianza e contra-varianza) e a cosa servono.

    Queste sono nozioni essenziali da sapere per usare "bene" i generics.
  • Re: Richiesta di aiuto per capire questo metodo :

    Grazie .
    Provo a cercare in rete qualcosa che parli di questi due nuovi argomenti .
  • Re: Richiesta di aiuto per capire questo metodo :

    Scusami Andbin dovrei risponderti quando ho le idee un po' più' chiare spero comunque di fare una domanda sensata.

    Ho letto qualche post da te pubblicato su questi due nuovi argomenti e mi viene subito da chiederti una cosa .
    Per esempio la differenza tra

    List<? extends Number> nums; ( Argomento su un post da te pubblicato )

    Anche qui non si sa quale è la parametrizzazione concreta ma c'è una informazione in più: è sicuramente Number o un sottotipo di Number.

    Quindi:
    nums = new ArrayList<Integer>(); // OK
    nums = new ArrayList<Long>(); // OK
    nums = new ArrayList<String>(); // NON compila perché String è fuori dal bound



    e la dicitura del metodo postato da me:

    (Map <? extends K ,? extends V > m)


    Questo vuol dire che ? extends K e ? extends V devono necessariamente essere parametrizzate a String

    Map<String,String> map = new HashMap<String,String>(); ???

    <String , String> e non di altro tipo ..??
  • Re: Richiesta di aiuto per capire questo metodo :

    Prima dovresti capire perché i generics di base sono "invarianti". Altrimenti non riusciresti a capire/apprezzare perché sono stati introdotti i wildcard e i bound.


    Per essere chiari: perché un List<String> NON è-un List<Object>
    Per capire questo si fa anche solitamente il confronto con gli array, dove un String[] invece è-un Object[]
  • Re: Richiesta di aiuto per capire questo metodo :

    Buongiorno Andbin .

    Ho ripreso questo post per vedere di riuscire a capire la differenza tra un String[] e Object[].
    Ho realizzato un piccolo esempio di codice che utilizza TreeSet.
    Prima ho utilizzato String[] e poi Object[].
    Con String[] il risultato e' la stringa ordinata in questo modo:
    A
    B
    C
    D
    F
    K
    L
    M
    CODICE :

    import java.util.Arrays;
    import java.util.TreeSet;
    public class Tree {
    public static void main(String args[]) throws Exception {
    String Frase ="A B C D F L M A K ";
    String[] Fraselista = Frase.split(" ");
    TreeSet<String> Parola = new TreeSet<>();
    Parola.addAll(Arrays.asList(Fraselista));
    for (String w : Parola)
    {
    System.out.println(w);
    }
    }
    }



    Cambiando String[] con Object[] ed eseguendo un cast String in questo modo:
    Il programma va in errore .


    Error: Main method not found in class Tree, please define the main method as:
    public static void main(String[] args)
    or a JavaFX application class must extend javafx.application.Application


    Credevo di riuscire a capire la differenza tra String[] e Object[] ma niente da fare .

    Andibin , come faccio a capire da un esempio la differenza tra String e Object ?

    Grazie.

    CODICE ERRATO:

    import java.util.Arrays;
    import java.util.TreeSet;
    public class Tree {
    public static void main(Object args[]) throws Exception {

    Object Frase ="A B C D F L M A K ";
    Object[] Fraselista = ((String) Frase).split(" ");
    TreeSet<Object> Parola = new TreeSet<>();
    Parola.add(Arrays.asList(Fraselista));
    for (Object w : Parola)
    {
    System.out.println(w);
    }
  • Re: Richiesta di aiuto per capire questo metodo :

    FabioJ ha scritto:


    Credevo di riuscire a capire la differenza tra String[] e Object[] ma niente da fare .
    Quindi non hai ancora compreso perché String[] è un sottotipo di Object[] mentre List<String> NON è un sottotipo di List<Object> ??
  • Re: Richiesta di aiuto per capire questo metodo :

    Precisamente .

    Vorrei capirlo eseguendo un programmino .
  • Re: Richiesta di aiuto per capire questo metodo :

    Vorrei partire da qui:

    object[] array = new String[10]; // String[] è un sottotipo di object[]
    array[0] = 10; // genera un'eccezione a runtime

    array[0] genera un'eccezione a runtime ?

    ( questo non ho capito )
  • Re: Richiesta di aiuto per capire questo metodo :

    Mi sono ricordato che le interfacce non si possono istanziare e list e' un'interfaccia forse e' per questo che
    List<String> NON è un sottotipo di List<Object>

    Potrebbe essere giusta questa risposta ??
  • Re: Richiesta di aiuto per capire questo metodo :

    FabioJ ha scritto:


    Mi sono ricordato che le interfacce non si possono istanziare e list e' un'interfaccia forse e' per questo che
    List<String> NON è un sottotipo di List<Object>

    Potrebbe essere giusta questa risposta ??
    No, non è questo il motivo !!!

    FabioJ ha scritto:


    Vorrei capirlo eseguendo un programmino .
    Non è tanto con un programmino .... cioè sì, puoi anche provare ma bisogna prima capire il concetto.

    Gli array in Java sono "covarianti". Ovvero se S e T sono due tipi e S è sottotipo di T, allora: S[] è un sottotipo di T[] . Questo è quanto specifica il linguaggio Java.
    In più c'è sapere il concetto basilare sugli array. Gli array sono completamente rappresentati a runtime. Quando istanzi un String[], all'interno dell'oggetto dell'array ci sono tutte le informazioni per tenere indicato che gli elementi sono di tipo String.

    Ora:

    String[] sarr = new String[10];
    Object[] oarr = sarr; // lecito e corretto

    Adesso hai un array Object[] e a questo punto ti verrebbe da pensare: allora posso mettere in un elemento un Integer .... dopotutto Integer è-un Object .....

    oarr[0] = new Integer(123); // NOOOOOO

    Questa riga COMPILA perfettamente ma a runtime causa un ArrayStoreException. L'ho detto prima: nell'oggetto array le informazioni ci sono tutte: "i miei elementi sono di tipo String". E questa informazione VIENE controllata ad ogni assegnamento agli elementi. Se il tipo è appropriato, ok. Altrimenti ArrayStoreException.
    Insomma, non è possibile "ravanare" il contenuto degli array con valori di tipo inappropriato, perché le informazioni sul tipo ci sono e vengono usate/applicate.

    -----------------------------

    I generics invece sono stati implementati per "erasure". Ovvero a runtime queste informazioni NON ci sono.

    List<String> slist = new ArrayList<String>();

    Nell'oggetto ArrayList NON c'è e non viene mantenuta a runtime alcuna informazione sul fatto che "è di String". I generics in sostanza "esistono" e sono controllati solo a livello di compilazione.

    List<Object> olist = slist; // SE questo fosse possibile ......
    olist.add(new Integer(123)); // QUI non c'è alcun controllo a runtime

    E se olist = slist fosse possibile allora magari molto più avanti:

    String str = slist.get(0); // FALLIREBBE perché l'oggetto è un Integer che non può essere castato a String.

    Insomma, se olist = slist FOSSE possibile, allora sarebbe possibile "ravanare" il contenuto delle collezioni, perché non ci sono controlli (NON essendoci informazioni mantenute a runtime). E tutta la teoria dei generics andrebbe a farsi friggere ....

    Per questo motivo è stato imposto che un List<S> NON è un sottotipo di List<T> anche se vale che S è un sottotipo di T.


    Adesso c'è qualche "luce" in più? sull'argomento
  • Re: Richiesta di aiuto per capire questo metodo :

    Si , Inizio a vedere un po' di luce sull'argomento.
    Spesso quando aggiungo codice nei miei programmi complicandomi la vita vado in tilt pero' per il momento e' tutto OK .

    Comunque vorrei provare a fare un'altra domanda sperando di non andare in tilt.

    Quando mi capita di incontrare questo tipo di codice per esempio :

    void putAll(Map <? extends K ,? extends V > m)


    c'e' un modo per capire subito che questa istruzione fa una determinata cosa senza andare
    nella piattaforma API 7 e leggere la spiegazione ?

    Forse questa capacita' si impara con la pratica pero' se ad un esami mi si presenta un'istruzione del genere o simile come riesco a cavarmela ?

    Per le altre istruzioni credo di non avere problemi pero' quando vedo < ? extends ... mi prende un colpo .

    Qualche suggerimento pratico per non andare in tilt .... grazie .
  • Re: Richiesta di aiuto per capire questo metodo :

    ? extends K si legge come "qualsiasi tipo che sia un sottotipo di K (o K stesso)".
    Inoltre sai per certo che l'oggetto passato come parametro viene usato in sola lettura (si può usare get() ma non put(), add(), ecc).
  • Re: Richiesta di aiuto per capire questo metodo :

    FabioJ ha scritto:


    void putAll(Map <? extends K ,? extends V > m)


    c'e' un modo per capire subito che questa istruzione fa una determinata cosa senza andare
    nella piattaforma API 7 e leggere la spiegazione ?
    Il "All" di putAll ti dovrebbe far subito pensare che il metodo aggiunge tutte le entry della mappa in argomento dentro la mappa su cui è invocato il metodo putAll.

    Poi riguardo il ? extends mi pare di averlo detto prima. Se hai una es. Map<Number,Object>, se NON ci fossero i due ? extends allora K è Number e V è Object e quindi potresti SOLO passare un altro Map<Number,Object>.

    Con i due ? extends, si rende più "ampia" la forma. Ovvero in un Map<Number,Object> posso aggiungere (perché HA senso) tutte le entry che provengono da un Map<Integer,String> o da un Map<Long,Date> perché il contenuto di queste mappe è lecito per la mappa di destinazione.
    Non ha ovviamente senso poter aggiungere le entry da una Map<String,Object>, perché String è FUORI dal bound "qualunque cosa sotto Number".
    Se fosse possibile, la mappa verrebbe ravanata .....

    xneo ha scritto:


    ? extends K si legge come "qualsiasi tipo che sia un sottotipo di K (o K stesso)".
    Inoltre sai per certo che l'oggetto passato come parametro viene usato in sola lettura (si può usare get() ma non put(), add(), ecc).
    Sì. Se hai es. ? extends Number puoi solo estrarre come Number. Non puoi inserire nulla (a parte un null letterale).

    List<? extends Number> nums = ........

    Se a nums venisse assegnato un List<Integer>, sarebbe lecito inserire un Integer. Ma se fosse un List<Long>? Ovviamente no.
    Appunto solo vedendo nums "non sai cosa gli è stato assegnato". E quindi è proibito passare qualcosa in input.

    P.S. giusto per chiarire: nums.add(null); è lecito!
  • Re: Richiesta di aiuto per capire questo metodo :

    Vorrei provare a fare qualche esercizio provando ad utilizzare proprio l'estensione <? extends ... sicuramente mi perdo pero' soltanto con gli esercizi si riesca a capire bene.
    Partendo dal semplice frammento di codice:
    Come posso utilizzare l'estensione <? extends ...?? potrei aggiungere alle lettere anche dei numeri ..
    Tipo TreeSet<E extends .....qualcosa ??


    import java.util.Arrays;
    import java.util.TreeSet;
    public class Tree {
    public static void main(String args[]) throws Exception {
    String Frase ="A B C D F L M A K ";
    String[] Fraselista = Frase.split(" ");
    TreeSet<String> Parola = new TreeSet<>();
    Parola.addAll(Arrays.asList(Fraselista));
    for (String w : Parola)
    {
    System.out.println(w);
    }
    }
    }
Devi accedere o registrarti per scrivere nel forum
16 risposte