Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 14
  1. #1
    Utente di HTML.it
    Registrato dal
    Apr 2014
    Messaggi
    76

    [Java/Generici] Istanziare oggetto generico?

    Ciao a tutti,
    come da titolo vorrei capire come posso istanziare un oggetto generico (dato che non è possibile fare una new T()).

    In particolare vorrei creara un metodo che legga un files riga per riga e che effettui la new di un generico tipo riga passando al costruttore la Stringa corrispondante alla riga, il metodo restituirà un'ArrayList di oggetti generici "Riga"...

    Potrei usare un generico T che estenda/implementi un'interfaccia/classeAstratta Row con un metodo (non costruttore) build/create? dovrei comunque creare un oggetto vuoto (cosa che non posso fare) per poi riempirlo con build/create...

    Qual'è il modo migliore per farlo?

    Vi Ringrazio in anticipo...

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    come da titolo vorrei capire come posso istanziare un oggetto generico (dato che non è possibile fare una new T()).
    Non puoi. Le classi "generiche" (pensa alle collezioni es. ArrayList o al Optional di Java 8) fanno solo da "contenitori", non solo loro che istanziano gli oggetti. Idem per metodi "generici", non sono loro a istanziare gli oggetti. Non direttamente. Un metodo generico potrebbe ricevere una implementazione di una interfaccia "generica" che fa da "producer" di oggetti.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    In particolare vorrei creara un metodo che legga un files riga per riga e che effettui la new di un generico tipo riga passando al costruttore la Stringa corrispondante alla riga, il metodo restituirà un'ArrayList di oggetti generici "Riga"...
    Non è un buonissimo approccio, perché innanzitutto obbliga la classe ad avere un costruttore che riceve la stringa e poi impone alla classe di "sapere" un formato di stringa ben preciso. Se fosse una classe Persona e il formato fosse di un csv ... cosa c'entra un csv con Persona? E se saltasse fuori un altro formato che fai?

    La cosa si risolve in altro modo, ragionando meglio a livello di "design" delle classi.
    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
    Apr 2014
    Messaggi
    76
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Non puoi. Le classi "generiche" (pensa alle collezioni es. ArrayList o al Optional di Java 8) fanno solo da "contenitori", non solo loro che istanziano gli oggetti. Idem per metodi "generici", non sono loro a istanziare gli oggetti. Non direttamente. Un metodo generico potrebbe ricevere una implementazione di una interfaccia "generica" che fa da "producer" di oggetti.


    Non e' un buonissimo approccio, percheè innanzitutto obbliga la classe ad avere un costruttore che riceve la stringa e poi impone alla classe di "sapere" un formato di stringa ben preciso. Se fosse una classe Persona e il formato fosse di un csv ... cosa c'entra un csv con Persona? E se saltasse fuori un altro formato che fai?

    La cosa si risolve in altro modo, ragionando meglio a livello di "design" delle classi.
    Non mi viene in mente una soluzione che garantisca un buon compromesso Efficienza/BuonaArchitettura...

    Mettiamo che io debba creare un ArrayList Oggetti Persona da file...
    Se io mi creo un primo strato che legge da File e "inietta" un'Oggetto parsificatore di Righe, potrei restituire un'array(o gia' un ArrayList) di:
    - Righe semplici (praticamente solo un Wrapper della String di readLine oppure una ClasseStatica/Singleton che restituisce stringhe)
    - Righe Csv (un Wrapper di Array di stringhe opportunamente splittate grazie ad un carattere separator oppure una ClasseStatica/Singleton che restituisce array di stringhe)
    - Altro???
    E magari inserire nel Parsificatore anche in carattere di Commento che permette di ingorare una riga...

    Poi pero' dovrei ancora "Castare" (scusa il temine improprio) il Tipo RigaCsv nel Tipo Persona e scorrere DI NUOVO l'array di Righe per copiarlo in quello di persone...

    Se poi volessi caricare anche ArrayList di Animali, Piante o Cose?

    Il modo piu' efficiente sarebbe un metodo personalizzato per ogni Classe, ma duplicherei tutto il codice:
    - OpenFile(path)
    - While(File.hasNextRow)
    --> readLine && saveOnArrayList
    - Close/FlushFile

    Una spintarella nella giusta direzione???
    Ultima modifica di Mrk31; 14-06-2016 a 12:17

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    Una spintarella nella giusta direzione???
    Quando si vogliono fare cose di questo tipo è bene tenere presente alcuni aspetti della OOP. Uno di questi è di individuare cosa "cambia" e cosa "non cambia".
    Cosa è che non cambia? Non cambia il modo di gestire un certo formato, es. CSV. Che nel CSV ci siano dati di persone, di animali o di piante, non cambia la logica di gestione. Andrai ad "aprire" il file sempre in un certo modo, leggere le righe in un certo modo, separare i dati in un certo modo, ecc... Questo non cambia e va quindi tenuto da una certa parte.

    Quello che cambia e che può variare anche molto è la "mappatura" dei dati, appunto come interpretare ed estrarre i dati da ciascuna riga logica del CSV. Insomma, ci possono essere "strategie" differenti. E questo va tenuto da un'altra parte, astraendola in modo da poter avere strategie differenti.

    Poi ci possono essere diverse strade per "mappare" i dati, che magari arrivano anche ad usare reflection, annotation e cose di questo tipo. Per il momento tralasciamo un momento questo aspetto un po' avanzato. Una possibile soluzione a livello di design potrebbe essere la seguente:

    - Una classe generica CSVFileReader<T>

    - Una interfaccia generica RowDataMapper<T> che potrebbe avere un solo metodo es.

    codice:
    public interface RowDataMapper<T> {
        T mapRow(RowData rowData);
    }

    - E la classe RowData "modella" una riga (del CSV in questo caso) e potrebbe avere metodi per:
    -- sapere il numero di colonne
    -- estrarre i dati da una certa colonna n magari con varianti per i vari tipi es. getInt(int colonna) / getString(int colonna) ecc...

    A questo punto basterebbe assegnare una implementazione di RowDataMapper nel CSVFileReader (tramite costruttore o setter ... ora non importa). Chi implementa RowDataMapper dovrà quindi implementare il mapRow per estrarre e creare un oggetto del tipo corretto. QUI puoi istanziare una certa classe, es. Persona o Animale o Pianta, perché la implementazione è concreta e conosci tu il tipo di dato.

    Alla fine l'uso finale potrebbe essere qualcosa del tipo:

    codice:
    CSVFileReader<Persona> csvReader = new CSVFileReader<>("persona.csv", new MyPersonaRowDataMapper());
    List<Persona> listaPersona = csvReader.readAll();
    
    ...
    csvReader.close();

    E MyPersonaRowDataMapper sarà qualcosa del tipo:

    codice:
    public class MyPersonaRowDataMapper implements RowDataMapper<Persona> {
        public Persona mapRow(RowData rowData) {
            // Qui PUOI istanziare un Persona
        }
    }
    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
    Apr 2014
    Messaggi
    76
    Quote Originariamente inviata da andbin Visualizza il messaggio
    codice:
    CSVFileReader<Persona> csvReader = new CSVFileReader<>("persona.csv", new MyPersonaRowDataMapper());
    List<Persona> listaPersona = csvReader.readAll();
    
    ...
    csvReader.close();
    Ok grazie mille tutto abbastanza chiaro, ho solo un dubbio nella parte che ho quotato, si potrebbe anche fare una cos del genere?

    codice:
    CSVFileReader<Persona> csvReader = new CSVFileReader<>(new MyPersonaRowDataMapper());
     //Passo solo il mapper
    
    List<Persona> listaPersona = csvReader.readAll("persona.csv"); 
    //Qui passo il path del file ed all'interno eseguo la file.close()
    
    //In questo modo posso fare tutte le readAll che mi pare con la stessa istanza...
    C'e qualche controindicazione?

    Nel tuo esempio cosa fa la csvReader.close(); un flush/close del file o anche altro?

    __________________________________________________ ____________________________________
    Leggero O.T.
    Una volta appresi tutti i vari concetti dell'"ingegneria del SW":
    - Ereditarieta', polimorfismo, Generici ecc...
    - Reflection (Su questa zoppico ancora un po')
    - Patter Architetturali (MVC, MVVM, ecc...)
    - Design Pattern (GOF, GRASP); High Coesion, Low Coupling, ecc...
    Di cui si trova anche parecchia documentazione, esempi nei vari linguaggi ecc...

    Mi trovo un po' perso nell'integrazione/alternanza/coesistenza/scelta dei vari concetti...

    Conosci buoni libri, link, guide di "Best Practice" per districarsi oltre andare ad "imitazione" di quanto gia' esistente (Librerie, Framework, ecc...)?

    Un'altro grande dubbio e':
    - Le classi statiche (come le variabili globali) sono "il male assoluto" (vabbe forse un po' esagerato, pero' diciamo che bisognerebbe pensare bene se sono indispensabili prima di utilizzarle)
    - al posto delle classi statiche potrei usare dei singleton...
    - ma sembrerebbe che anche i Singleton vadano "razionati" (oltre ad avere problemi in multi-thread se non adeguatamente implementati)
    - Quindi nel caso di utilizzo di metodi di "Utilita'" generale (uguali per molte/tutte le classi o comunque per classi che non avrebbe senso "imparentare") cos'altro si potrebbe usare usare?
    Ultima modifica di Mrk31; 14-06-2016 a 14:24

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    Ok grazie mille tutto abbastanza chiaro, ho solo un dubbio nella parte che ho quotato, si potrebbe anche fare una cos del genere?

    codice:
    CSVFileReader<Persona> csvReader = new CSVFileReader<>(new MyPersonaRowDataMapper());
     //Passo solo il mapper
    
    List<Persona> listaPersona = csvReader.readAll("persona.csv"); 
    //Qui passo il path del file ed all'interno eseguo la file.close()
    
    //In questo modo posso fare tutte le readAll che mi pare con la stessa istanza...
    C'e qualche controindicazione?
    No, nessuna controindicazione. Semplicemente è un "design" differente. In questo modo CSVFileReader diventa banalmente una "strategia" di lettura di un CSV per un certo tipo specifico ma senza sapere a priori su quale file. Vuol anche dire che ad esempio tu puoi passare un oggetto CSVFileReader (chiaramente parametrizzato, se passi un CSVFileReader<Persona> chi lo usa non può pensare di leggere animali o piante ...) ad un metodo che magari sa di dover leggere due file csv ben precisi di cui vuole ad esempio unire insieme gli oggetti Persona dei due file.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    Nel tuo esempio cosa fa la csvReader.close(); un flush/close del file o anche altro?
    Banalmente un close() sull'oggetto di I/O più esterno che è incapsulato nel CSVFileReader, un BufferedReader ad esempio.
    Ma se usi il design che hai appena detto, il close sarà quindi incapsulato nel readAll, chiaramente.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    Mi trovo un po' perso nell'integrazione/alternanza/coesistenza/scelta dei vari concetti...

    Conosci buoni libri, link, guide di "Best Practice" per districarsi oltre andare ad "imitazione" di quanto gia' esistente (Librerie, Framework, ecc...)?
    In questo momento non ho link/riferimenti precisi da indicarti.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    - Le classi statiche (come le variabili globali) sono "il male assoluto" (vabbe forse un po' esagerato, pero' diciamo che bisognerebbe pensare bene se sono indispensabili prima di utilizzarle)
    Una classe "statica" può essere solo "membro" di un'altra classe (è una nested static class). E si usano, non è quello "il male", di per sé.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    - al posto delle classi statiche potrei usare dei singleton...
    Probabilmente stai confondendo qualcosa .... una nested static class non c'entra nulla direttamente con il pattern "singleton".

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    - ma sembrerebbe che anche i Singleton vadano "razionati" (oltre ad avere problemi in multi-thread se non adeguatamente implementati)
    Sì ma il pattern singleton può avere svariate varianti a livello implementativo. Dipende se l'oggetto va creato subito o in modo lazy, se deve tenere conto della concorrenza (=sincronizzazione) oppure no.

    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    - Quindi nel caso di utilizzo di metodi di "Utilita'" generale (uguali per molte/tutte le classi o comunque per classi che non avrebbe senso "imparentare") cos'altro si potrebbe usare usare?
    Qui non ho ben capito il senso del dubbio. Se una classe ha solo metodi di "utilità" (come es. java.lang.Math o java.util.Collections) ha senso mettere un costruttore privato e poi avere i metodi tutti static.
    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
    Apr 2014
    Messaggi
    76
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Una classe "statica" può essere solo "membro" di un'altra classe (è una nested static class). E si usano, non è quello "il male", di per sé.

    Probabilmente stai confondendo qualcosa .... una nested static class non c'entra nulla direttamente con il pattern "singleton".

    Sì ma il pattern singleton può avere svariate varianti a livello implementativo. Dipende se l'oggetto va creato subito o in modo lazy, se deve tenere conto della concorrenza (=sincronizzazione) oppure no.

    Qui non ho ben capito il senso del dubbio. Se una classe ha solo metodi di "utilità" (come es. java.lang.Math o java.util.Collections) ha senso mettere un costruttore privato e poi avere i metodi tutti static.
    Intendevo che pur essendo due concetti nettamente distinti Singleton e Classe statica si "somigliano":
    - Non sono "istanziabili"
    - l'idea di utilizzo è che molti oggetti possano utilizzare la "stessa istanza" senza passarla come parametro, ma solo importandola
    - vengono utilizzati in modo simile
    es. CalsseStatica.metodo() Singleton.getInstance().metodo();
    La differenza principale è che la classe statica viene inizializzata "Subito ed in ogni caso", mentre il Singleton in modo "Lazy".

    Quindi potrebbero esserci casi in cui entrambi potrebbero essere "sovrapponibili/intercambiabili/entrambiValidi"...
    Ultima modifica di Mrk31; 14-06-2016 a 15:17

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    Intendevo che pur essendo due concetti nettamente distinti Singleton e Classe statica si "somigliano":
    - Non sono "istanziabili"
    - l'idea di utilizzo è che molti oggetti possano utilizzare la "stessa istanza" senza passarla come parametro, ma solo importandola
    - vengono utilizzati in modo simile
    es. CalsseStatica.metodo() Singleton.getInstance().metodo();
    La differenza principale è che la classe statica viene inizializzata "Subito ed in ogni caso", mentre il Singleton in modo "Lazy".

    Quindi potrebbero esserci casi in cui entrambi potrebbero essere "sovrapponibili/intercambiabili/entrambiValidi"...
    No.

    Una classe "static" (ripeto: deve essere "membro" di un'altra classe) PUO' essere istanziata.
    Una nested static class ha gli stessi identici principi (stesse regole, stesso ciclo di vita, ecc...) di una classe "top-level" (non contenuta dentro qualcosa). È semplicemente da vedere come se fosse in un "namespace" che è fatto dalla classe top-level che la contiene.

    codice:
    public class TopLevel {
        // ....
    
        public static class Nested {
            // ....
        }
    }

    Per poterla istanziare dall'esterno devi fare: new TopLevel.Nested()

    Tutto qui. Per il resto cambia nulla come regole e concetti.

    P.S. deduco che hai le idee un po' confuse su questo argomento.
    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
    Apr 2014
    Messaggi
    76
    Quote Originariamente inviata da andbin Visualizza il messaggio
    No.

    Una classe "static" (ripeto: deve essere "membro" di un'altra classe) PUO' essere istanziata.
    Una nested static class ha gli stessi identici principi (stesse regole, stesso ciclo di vita, ecc...) di una classe "top-level" (non contenuta dentro qualcosa). È semplicemente da vedere come se fosse in un "namespace" che è fatto dalla classe top-level che la contiene.

    codice:
    public class TopLevel {
        // ....
    
        public static class Nested {
            // ....
        }
    }

    Per poterla istanziare dall'esterno devi fare: new TopLevel.Nested()

    Tutto qui. Per il resto cambia nulla come regole e concetti.

    P.S. deduco che hai le idee un po' confuse su questo argomento.
    Probabilmente sono tardo , ma ancora non ci arrivo...

    Mettiamo che debba implementare, per esempio, una classe/libreria per avere una serie di metodi di utilità per la cifratura di stringhe:
    -con classe statica:
    codice:
    public static class HashUtils{
       public static String getMd5(String pwd) {
          //Restituisce la stringa cifrata in md5;
       }
    }
    --> Utilizzo:
    codice:
    String ciphredPwd = HashUtils.getMd5(pwd);
    -con Singleton:
    codice:
    public class HashUtils { 
       private static HashUtils instance = null;
    
       private/protected HashUtils() {}
    
       public static HashUtils getInstance() {
          if(instance == null) {
             instance = new HashUtils();
          }
          return instance;
       }
    
       public String getMd5(String pwd) {
          //Restituisce la stringa cifrata in md5;
       }
    }
    --> Utilizzo:
    codice:
    String ciphredPwd = HashUtils.getInstance().getMd5(pwd);
    L'unica differenza è che con il singleton avrei l'inizializzazione "pigra"...
    Ultima modifica di Mrk31; 14-06-2016 a 16:02

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    codice:
    public static class HashUtils{
       public static String getMd5(String pwd) {
          //Restituisce la stringa cifrata in md5;
       }
    }
    --> Utilizzo:
    codice:
    String ciphredPwd = HashUtils.getMd5(pwd);
    No. Questa classe HashUtils NON può essere "top level". Dovrebbe essere contenuta dentro un'altra classe. E se lo fosse, l'unica cosa (ripeto l'unica) che cambierebbe è a livello di naming, cioè di qualificazione del nome:

    String ciphredPwd = ClasseTopLevel.HashUtils.getMd5(pwd);


    Quote Originariamente inviata da Mrk31 Visualizza il messaggio
    -con Singleton:
    codice:
    public class HashUtils { 
       private static HashUtils instance = null;
    
       private/protected HashUtils() {}
    
       public static HashUtils getInstance() {
          if(instance == null) {
             instance = new HashUtils();
          }
          return instance;
       }
    
       public String getMd5(String pwd) {
          //Restituisce la stringa cifrata in md5;
       }
    }
    --> Utilizzo:
    codice:
    String ciphredPwd = HashUtils.getInstance().getMd5(pwd);
    L'unica differenza è che con il singleton avrei l'inizializzazione "pigra"...
    Ti ripeto che il concetto del pattern "singleton" non c'entra nulla con la differenza tra una classe "top level" e una "nested" (static).
    Ultima modifica di andbin; 14-06-2016 a 16:27
    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.