[Problema STATIC]Condivisione variabile tra classi

di il
18 risposte

[Problema STATIC]Condivisione variabile tra classi

Salve ragazzi, sono nuovo nel mondo java e ho un problema che credo sia legato più che altro alla teoria ma nonostante abbia letto molte guide non riesco a risolvere il problema.
Comunque ho due classi e un'interfaccia.
L'interfaccia "Command" mi definisce i comandi.
La classe CmdFactory definisce i comandi e altri metodi.
La classe CmdManager creo il manager dove andrà a prendere in input dei comandi e mi dovrà restituire un qualcosa, per esempio: nel CmdFactory ho un getPI() me ritorna il valore del pi greco e se scrivo PI il pogramma mi deve restituire 3.14.

Il mio programma è finito del tutto tranne che per un particolare: se creo due oggetti di tipo CmdManager se modifico o uno o l'altro la modifica avviene su entrambi. Il fatto (credo) sia dovuto alla lista di comandi dichiarata static. Infatti ho dichiarato una lista nel CmdManager dove vado ad aggiungere dei comandi tramite il metodo add(comando) situato in CmdManager. Però ho un metodo in CmdFactory, getHelp(), che deve prendere questa lista e restituire tutti i comandi che ho in quel momento in CmdManager. Quindi ho pensato: creo una lista di comandi Command[], la metto pubblica e la uso sia per CmdManager che per CmdFactory. Purtroppo Eclipse me la fa dichiarare "STATIC" e quindi se creo due oggeti diversi quella essendo static è sempre la stessa list per entrambi gli oggetti. Come posso ovviare al problema?

18 Risposte

  • Re: [Problema STATIC]Condivisione variabile tra classi

    KILLERIX ha scritto:


    Come posso ovviare al problema?
    Senza vedere esattamente che codice hai scritto ... e senza avere una idea più chiara di cosa devono rappresentare quei tipi e quali sono le loro responsabilità (in particolare cosa deve fare in generale un "command"), è un po' difficile da dire.
  • Re: [Problema STATIC]Condivisione variabile tra classi

    package hw1.cmd;
    
    /** <b>IMPLEMENTARE I METODI SECONDO LE SPECIFICHE DATE NEI JAVADOC.</b>
     * <br>
     * Una classe con factory methods per creare alcuni comandi. Ogni factory method
     * ritorna uno specifico comando di tipo {@link hw1.cmd.Command}. Sarebbe bene che
     * ognuno di questi ritorni ad ogni invocazione sempre lo stesso oggetto. */
    public class CmdFactory {
        /** Ritorna un comando per ottenere il valore di pigreco. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se la stringa di comando non è
         * esattamente uno dei nomi del comando.
         * <pre>
         * Nomi: "pi", "Pi", "PI"
         * Doc:  "pi  --> valore di Pi greco"
         * Esempi:
         *     execute("pi") ritorna "3.141592653589793"
         *     execute("pi g") lancia IllegalArgumentException
         * </pre>
         * @return un comando per ottenere il valore di pigreco */
        public static Command getPI() {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna un comando per sommare una serie di numeri. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come una sequenza di
         * numeri, interi o con virgola, separati da whitespaces.
         * <pre>
         * Nomi: "+", "sum"
         * Doc:  "+ x y ... z  --> somma x+y+...+z"
         * Esempi:
         *     execute("+ 1   2.5 -3") ritorna "0.5"
         *     execute("sum 1 2.5    -3") ritorna "0.5"
         *     execute("+1   2.5 -3") ritorna "0.5"
         *     execute("+") ritorna "0.0"
         *     execute("+ 1 2 3 4") ritorna "10.0"
         *     execute("+ 1 2 a") lancia IllegalArgumentException
         * </pre>
         * @return un comando per sommare una serie di numeri */
        public static Command getSum() {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna un comando per l'elevazione a potenza. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come due numeri,
         * interi o con virgola, separati da whitespaces.
         * <pre>
         * Nomi: "^", "**", "pow"
         * Doc:  "pow x y  --> x elevato a y"
         * Esempi:
         *     execute("pow2 5") ritorna "32.0"
         *     execute("^ 1.2 -0.6") ritorna "0.8963781307771418"
         *     execute("** -1 0.5") ritorna "NaN"
         *     execute("pow 2") lancia IllegalArgumentException
         * </pre>
         * @return un comando per l'elevazione a potenza */
        public static Command getPow() {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna un comando per fattorizzare un intero. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come un numero intero
         * maggiore od uguale a 2. Nell'output i fattori sono elencati in ordine crescente.
         * <pre>
         * Nomi: "factorize"
         * Doc:  "factorize n  --> fattorizzazione di n"
         * Esempi:
         *     execute("factorize 1504") ritorna "2(5) 47"
         *     execute("factorize 123400272626252672") ritorna "2(7) 29(2) 1097 1044969287"
         *     execute("factorize1000") ritorna "2(3) 5(3)"
         *     execute("factorize 15 s") lancia IllegalArgumentException
         * </pre>
         * @return un comando per fattorizzare un intero */
        public static Command getFactorize() {
            throw new UnsupportedOperationException();
        }
    
    
        /** @return un array con tutti i comandi ritornati dai metodi di questa classe */
        public static Command[] getAll() {
            throw new UnsupportedOperationException();
        }
    }


    package hw1.cmd;
    
    /** <b>IMPLEMENTARE I METODI SECONDO LE SPECIFICHE DATE NEI JAVADOC.</b>
     * <br>
     * Un oggetto {@code CmdManager} è un manager di un insieme di comandi (di tipo
     * {@link hw1.cmd.Command}) che permette di ottenere la documentazione di ognuno e di
     * eseguire stringhe di comando relative ai comandi gestiti. Un manager garantisce
     * sempre che non ci siano due comandi gestiti che hanno un nome uguale. */
    public class CmdManager {
        /** Crea un manager di comandi con i comandi specificati. Il manager creato ha
         * sempre un comando di help per ottenere informazioni sui comandi gestiti. Tale
         * comando è così specificato:
         * <pre>
         * Nomi: "help","h"
         * Doc:  "h cmd  --> documentazione del comando cmd"
         * Esempi:
         *     "h"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         *     "help"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         *     "h sum"  --> "+ x y ... z  --> somma x+y+...+z"
         *     "help +"  --> "+ x y ... z  --> somma x+y+...+z"
         *     "h nocmd"  --> IllegalArgumentException
         * </pre>
         *
         * @param cc i comandi gestiti dal manager
         * @throws NullPointerException     se uno dei comandi è null
         * @throws IllegalArgumentException se due comandi hanno un nome in comune
         *                                  (compreso il comando di help). */
        public CmdManager(Command... cc) {
            throw new UnsupportedOperationException();
        }
    
        /** Aggiunge un comando al manager.
         *
         * @param c il comando da aggiungere
         * @throws NullPointerException     se il comando è null
         * @throws IllegalArgumentException se il comando ha un nome che è di uno dei
         *                                  comandi già presenti (compreso il comando di help). */
        public void add(Command c) {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna una stringa con tante linee quanti sono i comandi del manager e in
         * ogni linea elenca i nomi di uno dei comandi. Esempio
         * <pre>
         * "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         * </pre>
         * L'ordine è arbitrario.
         *
         * @return una stringa con i nomi dei comandi */
        public String commands() {
            throw new UnsupportedOperationException();
        }
    
        /** Esegue la stringa di comando e ritorna il risultato. Esempi
         * <pre>
         * "h"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         * null  --> NullPointerException
         * "hh"  --> IllegalArgumentException
         * "sum 1 2"  --> "3"
         * "sum 1 2 x"  --> IllegalArgumentException
         * </pre>
         *
         * @param cmd un comando da eseguire
         * @return il risultato dell'esecuzione della stringa di comando
         * @throws NullPointerException     se la stringa di comando è null
         * @throws IllegalArgumentException se non c'è un comando con il nome dato o se
         *                                  la stringa di comando non è valida, cioè il
         *                                  metodo execute del relativo comando lancia l'eccezione */
        public String execute(String cmd) {
            throw new UnsupportedOperationException();
        }
    }
    

    package hw1.cmd;
    
    import java.util.List;
    
    /** Rappresenta un comando capace di eseguire stringhe di comando. La sintassi di una
     * stringa di comando è
     * <pre>
     *     cmd args
     * </pre>
     * Cioè una stringa che inizia con uno dei nomi {@code cmd} del comando seguito
     * dagli eventuali argomenti separati tra loro da uno o più spazi. Ad esempio un
     * comando per effettuare somme potrebbe avere i seguenti quattro nomi:
     * <pre>
     *     + sum Sum SUM
     * </pre>
     * e accettare stringhe di comando come:
     * <pre>
     *     + 2 4 2.5
     *     sum 4.5 4
     *     Sum 8.5
     *     SUM 1 2 4 1.5
     * </pre>
     * In tutti i casi il risultato sarebbe la stringa {@code "8.5"}. */
    public interface Command {
        /** Ritorna la lista dei nomi di questo comando. La lista deve essere non
         * modificabile come {@link java.util.Collections#unmodifiableList}. L'ordine
         * è arbitrario.
         * @return la lista dei nomi di questo comando */
        List<String> getNames();
    
        /** Esegue la stringa di comando e ritorna il risultato. Se la stringa di comando
         * non è valida, lancia IllegalArgumentException.
         * @param cmd  la stringa di comando da eseguire
         * @return il risultato dell'esecuzione della stringa di comando
         * @throws IllegalArgumentException  se la stringa di comando non è valida */
        String execute(String cmd);
    
        /** @return la documentazione di questo comando */
        String doc();
    }
    
  • Re: [Problema STATIC]Condivisione variabile tra classi

    A me serve semplicemente avere una lista di comandi (Command[] x) dove inserire periodicamente i miei comandi. Ma questa lista deve essere condivisa tra le classi ma alla creazione di un nuovo oggetto anch'essa deve essere nuova e non la stessa!

    Infatti:
    Se printo il codice della lista che creo col primo oggetto
    [Lhw1.cmd.Command;@677327b6
    [Lhw1.cmd.Command;@14ae5a5

    dopo quando creo il secondo oggetto ecco che riprende la lista del primo oggetto e non me la deve prendere!!!!!!!!!!!!!! :'(
    [Lhw1.cmd.Command;@14ae5a5
    [Lhw1.cmd.Command;@7f31245a
  • Re: [Problema STATIC]Condivisione variabile tra classi

    A me serve semplicemente avere una lista di comandi (Command[] x) dove inserire periodicamente i miei comandi. Ma questa lista deve essere condivisa tra le classi ma alla creazione di un nuovo oggetto anch'essa deve essere nuova e non la stessa!
    Continuo a non capire... vuoi una lista unica o una lista per ogni istanza?
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Mi serve una lista diversa per ogni istanza!
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Allora semplicemente non dichiararla static
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Se non la dichiaro static la Classe CmdManager funziona perfettamente. Però questa lista la devo usare anche in CmdFactory e li se la uso me la fa obbligatoriamente mettere static!
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Cosa fa esattamente CmdFactory?
  • Re: [Problema STATIC]Condivisione variabile tra classi

    public static Command getPI() {
        	Command p = new Command() {
    			
        		@Override
                public List<String> getNames() {
                    List<String> pLista = Arrays.asList("pi","Pi","PI");
                    return pLista;
                }
    
                @Override
                public String execute(String cmd) {
                	
                	if (cmd.length()>3){throw new IllegalArgumentException();}
                	if (cmd.length()>2 && !cmd.substring(2, 3).equals(" ")){throw new IllegalArgumentException();}
    
                	return "3.141592653589793";
                }
                
    
                @Override
                public String doc() {
                    return "pi  --> valore di Pi greco";
    
    			}
    		};
    		return p;
        }

    Questo è uno dei tanti comandi all'interno del CmdFactory. Il getNames() mi dice quali sono le stringhe che andandole a mettere nel CmdManager accetta e mi restituisca cosi il 3.14 gestito dall' execute(cmd). Il doc() mi restituisce la documentazione del comando.
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Non capisco a cosa ti serve dichiararla static...

    Io ho capito che intendi fare una cosa del genere:
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /** <b>IMPLEMENTARE I METODI SECONDO LE SPECIFICHE DATE NEI JAVADOC.</b>
    * <br>
    * Un oggetto {@code CmdManager} è un manager di un insieme di comandi (di tipo
    * {@link hw1.cmd.Command}) che permette di ottenere la documentazione di ognuno e di
    * eseguire stringhe di comando relative ai comandi gestiti. Un manager garantisce
    * sempre che non ci siano due comandi gestiti che hanno un nome uguale. */
    public class CmdManager {
        
        List<Command> cmds;
        /** Crea un manager di comandi con i comandi specificati. Il manager creato ha
         * sempre un comando di help per ottenere informazioni sui comandi gestiti. Tale
         * comando è così specificato:
         * <pre>
         * Nomi: "help","h"
         * Doc:  "h cmd  --> documentazione del comando cmd"
         * Esempi:
         *     "h"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         *     "help"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         *     "h sum"  --> "+ x y ... z  --> somma x+y+...+z"
         *     "help +"  --> "+ x y ... z  --> somma x+y+...+z"
         *     "h nocmd"  --> IllegalArgumentException
         * </pre>
         *
         * @param cc i comandi gestiti dal manager
         * @throws NullPointerException     se uno dei comandi è null
         * @throws IllegalArgumentException se due comandi hanno un nome in comune
         *                                  (compreso il comando di help). */
        public CmdManager(Command... cc) {
            cmds = new ArrayList<>();
            
            cmds.addAll(Arrays.asList(cc));
        }
    
        /** Aggiunge un comando al manager.
         *
         * @param c il comando da aggiungere
         * @throws NullPointerException     se il comando è null
         * @throws IllegalArgumentException se il comando ha un nome che è di uno dei
         *                                  comandi già presenti (compreso il comando di help). */
        public void add(Command c) {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna una stringa con tante linee quanti sono i comandi del manager e in
         * ogni linea elenca i nomi di uno dei comandi. Esempio
         * <pre>
         * "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         * </pre>
         * L'ordine è arbitrario.
         *
         * @return una stringa con i nomi dei comandi */
        public String commands() {
            StringBuilder builder = new StringBuilder();
            
            cmds.stream().forEach((c) -> {
                c.getNames().stream().forEach((s) -> {
                    builder.append(s);
                    builder.append(" ");
                });
                
                builder.append("\n");
                });
            
            return builder.toString();
        }
    
        /** Esegue la stringa di comando e ritorna il risultato. Esempi
         * <pre>
         * "h"  --> "h,help\npi,Pi,PI\n+,sum\n^,**,pow\nfactorize\n"
         * null  --> NullPointerException
         * "hh"  --> IllegalArgumentException
         * "sum 1 2"  --> "3"
         * "sum 1 2 x"  --> IllegalArgumentException
         * </pre>
         *
         * @param cmd un comando da eseguire
         * @return il risultato dell'esecuzione della stringa di comando
         * @throws NullPointerException     se la stringa di comando è null
         * @throws IllegalArgumentException se non c'è un comando con il nome dato o se
         *                                  la stringa di comando non è valida, cioè il
         *                                  metodo execute del relativo comando lancia l'eccezione */
        public String execute(String cmd) {
            throw new UnsupportedOperationException();
        }
    }
    import java.util.Arrays;
    import java.util.List;
    
    
    /** <b>IMPLEMENTARE I METODI SECONDO LE SPECIFICHE DATE NEI JAVADOC.</b>
    * <br>
    * Una classe con factory methods per creare alcuni comandi. Ogni factory method
    * ritorna uno specifico comando di tipo {@link hw1.cmd.Command}. Sarebbe bene che
    * ognuno di questi ritorni ad ogni invocazione sempre lo stesso oggetto. */
    public class CmdFactory {
        /** Ritorna un comando per ottenere il valore di pigreco. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se la stringa di comando non è
         * esattamente uno dei nomi del comando.
         * <pre>
         * Nomi: "pi", "Pi", "PI"
         * Doc:  "pi  --> valore di Pi greco"
         * Esempi:
         *     execute("pi") ritorna "3.141592653589793"
         *     execute("pi g") lancia IllegalArgumentException
         * </pre>
         * @return un comando per ottenere il valore di pigreco */
        public static Command getPI() {
            Command p = new Command() {
             
              @Override
                public List<String> getNames() {
                    List<String> pLista = Arrays.asList("pi","Pi","PI");
                    return pLista;
                }
    
                @Override
                public String execute(String cmd) {
                   
                   if (cmd.length()>3){throw new IllegalArgumentException();}
                   if (cmd.length()>2 && !cmd.substring(2, 3).equals(" ")){throw new IllegalArgumentException();}
    
                   return "3.141592653589793";
                }
                
    
                @Override
                public String doc() {
                    return "pi  --> valore di Pi greco";
    
             }
          };
          return p;
        }
    
        /** Ritorna un comando per sommare una serie di numeri. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come una sequenza di
         * numeri, interi o con virgola, separati da whitespaces.
         * <pre>
         * Nomi: "+", "sum"
         * Doc:  "+ x y ... z  --> somma x+y+...+z"
         * Esempi:
         *     execute("+ 1   2.5 -3") ritorna "0.5"
         *     execute("sum 1 2.5    -3") ritorna "0.5"
         *     execute("+1   2.5 -3") ritorna "0.5"
         *     execute("+") ritorna "0.0"
         *     execute("+ 1 2 3 4") ritorna "10.0"
         *     execute("+ 1 2 a") lancia IllegalArgumentException
         * </pre>
         * @return un comando per sommare una serie di numeri */
        public static Command getSum() {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna un comando per l'elevazione a potenza. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come due numeri,
         * interi o con virgola, separati da whitespaces.
         * <pre>
         * Nomi: "^", "**", "pow"
         * Doc:  "pow x y  --> x elevato a y"
         * Esempi:
         *     execute("pow2 5") ritorna "32.0"
         *     execute("^ 1.2 -0.6") ritorna "0.8963781307771418"
         *     execute("** -1 0.5") ritorna "NaN"
         *     execute("pow 2") lancia IllegalArgumentException
         * </pre>
         * @return un comando per l'elevazione a potenza */
        public static Command getPow() {
            throw new UnsupportedOperationException();
        }
    
        /** Ritorna un comando per fattorizzare un intero. Il metodo
         * {@link hw1.cmd.Command#execute(String)} del comando ritornato lancia
         * {@link java.lang.IllegalArgumentException} se nella stringa di comando ciò
         * che segue il nome del comando non è interpretabile come un numero intero
         * maggiore od uguale a 2. Nell'output i fattori sono elencati in ordine crescente.
         * <pre>
         * Nomi: "factorize"
         * Doc:  "factorize n  --> fattorizzazione di n"
         * Esempi:
         *     execute("factorize 1504") ritorna "2(5) 47"
         *     execute("factorize 123400272626252672") ritorna "2(7) 29(2) 1097 1044969287"
         *     execute("factorize1000") ritorna "2(3) 5(3)"
         *     execute("factorize 15 s") lancia IllegalArgumentException
         * </pre>
         * @return un comando per fattorizzare un intero */
        public static Command getFactorize() {
            throw new UnsupportedOperationException();
        }
    
    
        /** @return un array con tutti i comandi ritornati dai metodi di questa classe */
        public static Command[] getAll() {
            throw new UnsupportedOperationException();
        }
    }
    public class Loader {
    
     
        public static void main(String[] args){
           
            CmdManager cmdManager = new CmdManager(CmdFactory.getPI(), CmdFactory.getPI());
            
            System.out.println(cmdManager.commands());
            
            System.out.println("*****");
            
            System.out.println(new CmdManager().commands());
            
        }
    
    }
    
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Io non voglio dichiararla static ma me la fa dichiarare ECLIPSE quando la voglio richiamare da CmdFactory! Devo richiamarla nel CmdFactory quando uso il getHelp() che vado ad esplorare la lista per sapere i comandi che ho nel Manager in quel momento......

    IN poche parole mi serve che questa lista sia in comune tra tutte la classi e che non sia static! Esiste un modo?
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Devo richiamarla nel CmdFactory quando uso il getHelp() che vado ad esplorare la lista per sapere i comandi che ho nel Manager in quel momento......
    cosa??? dov'è il getHelp() ? non lo vedo nel codice che hai postato prima

    se devi richiamare dal CmdFactory un metodo su ogni istanza di CmdManager devi avere all'interno del CmdFactory una lista di tutte le istanze di CmdManager. Così puoi richiamare il metodo di ogni elemento nella lista.

    se ho capito cosa stai tentando di fare:
    per richiamare un metodo di una classe di cui non hai un riferimento alle istanze allocate devi perforza dichiararlo static.

    PS: questo è Java, non Eclipse
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Che io sappia no, anche perchè

    static = comune a tutte le istanze della classe
  • Re: [Problema STATIC]Condivisione variabile tra classi

    Si c'è anche l'help che ho dovuto creare personalmente.
    Cmq non capisco perchè ciò si così complicato. Nella foto c'è l'inizio del CmdFactory e alla riga 48 è la prima volta che mi serve prendere i dati che ho nella cmdList situata nel CmdManager. E' li che mi da l'errore e mi consiglia di metterla static ma mettendo la cmdList static rimane uguale per ogni istanza di CmdManager! Quindi mi serve che questa lista, ogni volta che faccio CmdManager x = new CmdManager(), sia differente dal precedente oggetto. Non capisco però come ovviare al problema secondo la tua soluzione....
Devi accedere o registrarti per scrivere nel forum
18 risposte