Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di Rplus
    Registrato dal
    Mar 2002
    Messaggi
    150

    [java] passaggio parametri

    volevo creare un programma che dato un vettore dichiarato nel main lo visualizzava, ordinava, e rivisualizzava di nuovo..

    da quello che ho capito m pare però che non sia possibile effettuare un passaggio per indirizzo, giusto?

    come faccio allora ad ordinare questo array facendo in modo che le modifiche siano effettive e visibili a tutto il main? m seccherebbe ordinarlo dentro al main, vorrei farlo con un metodo apposito..

    questo è il sorgente:
    codice:
    public class Vettore {
    	
    	//visualizza un vettore
    	static void visualizzavet(int[]vet) {
    		for (int i=0;i<vet.length;i++)
    			System.out.print(vet[i]+" ");
    		System.out.println();
    	}
    	
    	//ordina un vettore
    	static int[] ordinavet(int[] vet) {
    		for (int i=0;i<vet.length-1;i++)
    			for (int j=1;j<vet.length;j++) {
    				int comodo=i;
    				i=j;
    				j=comodo;
    			}
    		return vet;
    	}
    	
    	//main
    	public static void main(String[] argv) {
    		int[] vet = new int[argv.length];
    		for (int i=0;i<argv.length;i++)
    			vet[i]=Integer.parseInt(argv[i]);
    		visualizzavet(vet);
    		ordinavet(vet);
    		visualizzavet(vet);
    	}
    
    }
    grazie a tutti

  2. #2

    Re: [java] passaggio parametri

    Originariamente inviato da Rplus
    codice:
    public class Vettore {
    	//main
    	public static void main(String[] argv) {
    		int[] vet = new int[argv.length];
    		for (int i=0;i<argv.length;i++)
    			vet[i]=Integer.parseInt(argv[i]);
    		visualizzavet(vet);
    		vet = ordinavet(vet); //così
    		visualizzavet(vet);
    	}
    
    }
    grazie a tutti
    Il centro dell'attenzione non è sempre un buon posto in cui trovarsi

    Mai discutere con uno stupido, la gente potrebbe non capire la differenza. (O. W.)

  3. #3
    da quello che ho capito m pare però che non sia possibile effettuare un passaggio per indirizzo, giusto?
    la variabile vet rappresenta una copia della variabile che si riferisce al vettore di partenza, però i valori ai quali accedi vet[0] vet[1] ecc sono proprio quelli del primo vettore. Per cui se modifichi uno di questi dentro la funzione, cosa che dovrebbe fare la funzione ordina, il risultato lo ottieni gia nel tuo vettore senza aver bisogno di farlo ritornare al metodo.

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da robydrupo
    la variabile vet rappresenta una copia della variabile che si riferisce al vettore di partenza, però i valori ai quali accedi vet[0] vet[1] ecc sono proprio quelli del primo vettore. Per cui se modifichi uno di questi dentro la funzione, cosa che dovrebbe fare la funzione ordina, il risultato lo ottieni gia nel tuo vettore senza aver bisogno di farlo ritornare al metodo.
    In realtà non è una copia: è proprio lo stesso vettore!
    In Java tutti gli oggetti sono passati per riferimento.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  5. #5
    Originariamente inviato da LeleFT
    In realtà non è una copia: è proprio lo stesso vettore!
    In Java tutti gli oggetti sono passati per riferimento.


    Ciao.
    No, non è proprio esatto. In un metodo che ha come parametro un oggetto tu hai una copia della variabile orginale che si riferisce all'oggetto, e mai l'oggetto stesso.

    esempio:

    codice:
    public static void main(String[] args){
      String[] array1 = {"1","2","3","4","5"};
      String[] array2 = {"5","4","3","2",1"};
      scambia1(array1, array2);
      stampaVett(array1);
      scambia2(array1, array2);
      stampaVett(array1);
    }
    
    static void scambia1(String[] v1, String[] v2){
      String[] appoggio = v1;
      v1 = v2;
      v2 = appoggio;
    }
    
    static void scambia2(String[] v1, String[] v2){
      for(int x = 0; x < v1.lenght; x++){
         int appoggio = v1[x];
         v1[x] = v2[x];
         v2[x] = appoggio;
      }
    }
    Col primo in realtà scambi solamente le variabili di metodo (che stanno nello stack). Così facendo, le copie delle variabili all'interno si riferiscono ai vettori invertiti, senza però influire sulle variabili del main. Nel tuo metodo main non avrai il risultato ottenuto, ma array1 e array2 punteranno sempre all'array di partenza(heap).
    Nel secondo invece vai ad operare direttamente sui valori dell'array, per cui vai a modificare i valori memorizzati nello heap, utilizzando le variabili locali che si riferiscono ai due array. Col secondo otterrai un vero scambio.

    scusate la poca chiarezza, ma putroppo non so spiegarmi molto bene!

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da robydrupo
    No, non è proprio esatto. In un metodo che ha come parametro un oggetto tu hai una copia della variabile orginale che si riferisce all'oggetto, e mai l'oggetto stesso.

    esempio:

    codice:
    public static void main(String[] args){
      String[] array1 = {"1","2","3","4","5"};
      String[] array2 = {"5","4","3","2",1"};
      scambia1(array1, array2);
      stampaVett(array1);
      scambia2(array1, array2);
      stampaVett(array1);
    }
    
    static void scambia1(String[] v1, String[] v2){
      String[] appoggio = v1;
      v1 = v2;
      v2 = appoggio;
    }
    
    static void scambia2(String[] v1, String[] v2){
      for(int x = 0; x < v1.lenght; x++){
         int appoggio = v1[x];
         v1[x] = v2[x];
         v2[x] = appoggio;
      }
    }
    Col primo in realtà scambi solamente le variabili di metodo (che stanno nello stack). Così facendo, le copie delle variabili all'interno si riferiscono ai vettori invertiti, senza però influire sulle variabili del main. Nel tuo metodo main non avrai il risultato ottenuto, ma array1 e array2 punteranno sempre all'array di partenza(heap).
    Nel secondo invece vai ad operare direttamente sui valori dell'array, per cui vai a modificare i valori memorizzati nello heap, utilizzando le variabili locali che si riferiscono ai due array. Col secondo otterrai un vero scambio.

    scusate la poca chiarezza, ma putroppo non so spiegarmi molto bene!
    Questo perchè in Java non è possibile modificare i puntatori tramite una chiamata a procedura (o metodo), se non tramite l'assegnazione.
    Ma se dai un'occhiata a ciò che accade nel tuo metodo scambia1:
    codice:
    public static void main(String[] args){
      String[] array1 = {"1","2","3","4","5"};
      String[] array2 = {"5","4","3","2",1"};
      scambia1(array1, array2);
      stampaVett(array1);
      scambia2(array1, array2);
      stampaVett(array1);
    }
    
    static void scambia1(String[] v1, String[] v2){
      String[] appoggio = v1;
      v1 = v2;
      v2 = appoggio;
      stampaVett(v1);
    }
    
    static void scambia2(String[] v1, String[] v2){
      for(int x = 0; x < v1.lenght; x++){
         int appoggio = v1[x];
         v1[x] = v2[x];
         v2[x] = appoggio;
      }
    }
    noterai che i puntatori, tramite l'istruzione di assegnazione. sono stati modificati.
    Questo perchè in Java la nozione di puntatore viene resa trasparente.

    Quello che accade, quindi, è che viene passata una copia del puntatore, ma non una copia dell'oggetto.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  7. #7
    Originariamente inviato da LeleFT
    noterai che i puntatori, tramite l'istruzione di assegnazione. sono stati modificati.
    Questo perchè in Java la nozione di puntatore viene resa trasparente.


    Ciao.
    chiaro, l'avevo scritto sopra. Anche perchè se non erano modificati li....
    quello che però sto cercando di dire, è che ogni procedura lavora su una copia della variabile passata come parametro, sia che il tipo sia primitivo, sia che il tipo sia un oggetto

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da robydrupo
    chiaro, l'avevo scritto sopra. Anche perchè se non erano modificati li....
    quello che però sto cercando di dire, è che ogni procedura lavora su una copia della variabile passata come parametro, sia che il tipo sia primitivo, sia che il tipo sia un oggetto
    E' quest'ultima cosa che non è esatta. Controesempio:
    codice:
    public class Cript {
       public static void main(String[] args){
         M ogg = new M(0);
         metodo( ogg );
         System.out.println( ogg.stampa() );
       }
    
       static void metodo(M o){
          o.modifica();
       }
    }
    
    public class M {
       private int i;
       public M(int i) { this.i = i; }
       public void modifica() { i++; }
       public String stampa() { return "" + i; }
    }
    Qui l'oggetto ogg viene modificato! Il metodo metodo() non lavora su una copia dell'oggetto M, ma sullo stesso oggetto M. Ovvero tramite una copia del puntatore.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  9. #9
    un'oggetto e una variabile che si riferisce ad un oggetto sono due cose distinte! è chiaro che lavora sull'oggetto e non su una copia dell'oggetto, ma la variabile che tu usi per fare ogg.modifica(); è solamente una copia della variabile che hai passato come parametro...nè più nè meno di una variabile di tipo primitivo. La differenza sta che una variabile che si riferisce ad un oggetto "punta" all'oggetto vero e proprio, per cui richiamando metodi o campi tramite l'operatore . avrai le modifiche che desideri, mentre assegnando per esempio ogg = null non avrai effetti sul tuo oggetto di partenza.

  10. #10
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,304
    Originariamente inviato da robydrupo
    La differenza sta che una variabile che si riferisce ad un oggetto "punta" all'oggetto vero e proprio, per cui richiamando metodi o campi tramite l'operatore . avrai le modifiche che desideri...
    Su questo non ci sono dubbi... come ho detto qualche post più su al passaggio del parametro si ha una copia dell'indirizzo.
    un'oggetto e una variabile che si riferisce ad un oggetto sono due cose distinte! è chiaro che lavora sull'oggetto e non su una copia dell'oggetto, ma la variabile che tu usi per fare ogg.modifica(); è solamente una copia della variabile che hai passato come parametro...nè più nè meno di una variabile di tipo primitivo [...] mentre assegnando per esempio ogg = null non avrai effetti sul tuo oggetto di partenza.
    Qui non sei preciso. Il fatto che assegnando null all'oggetto del metodo non ottengo che l'oggetto di partenza venga rimosso è solo una questione di dangling pointers.
    Lo stesso, infatti, succede se pongo a null l'oggetto di partenza: all'interno del metodo l'oggetto continua ad esistere e può essere usato. Questo perchè la JVM nota che c'è ancora un riferimento attivo all'oggetto e questo non viene rimosso. Altro esempio:
    codice:
    import java.awt.*;
    import javax.swing.*;
    
    public class Classe extends JFrame {
    
       private class T extends Thread {
          private JTextField jtfPrivata;
          private int i;
          public T(JTextField jtfPrivata) { this.jtfPrivata = jtfPrivata; }
          public void run() {
             try {
                while (i<10) {
                   i++;
                   jtfPrivata.setText("" + i);
                   sleep(500);
                }
             } catch (Exception e) { e.printStackTrace(); }
          }
       }
    
    
       private JTextField jtf;
       private T t;
    
       public Classe() {
          getContentPane().setLayout(null);
          jtf = new JTextField();
          jtf.setBounds(20, 20, 150, 25);
          getContentPane().add(jtf);
          t = new T(jtf);
          t.start();
          jtf = null;
          System.out.println( jtf );
          setDefaultCloseOperation(EXIT_ON_CLOSE);
          setSize(300, 300);
          setVisible(true);
       }
    
       public static void main(String [] args) {
          Classe c = new Classe();
       }
    }
    In questo esempio creo una JTextField nella classe principale. La passo come parametro al costruttore del Thread, avvio il thread e pongo a null l'oggetto appena passato come parametro (l'oggetto originale). Risultato: il thread continuerà ad aggiornare la JTextField senza lanciare alcuna NullPointerException. Questo perchè dopo aver posto a null jtf l'unico riferimento ancora attivo alla JTExtField diventa quello del Thread e ciò è condizione sufficiente per non rimuovere dallo Heap la JTextField.
    Questo a dimostrazione del fatto che in Java qualsiaso "oggetto" è in realtà un puntatore. Solo che il programmatore non ne ha l'impressione. Il passaggio di oggetti, quindi, si trasforma in un passaggio di puntatori che vengono copiati in una nuova variabile. Le varie modifiche dei puntatori non influiscono sui riferimenti precedentemente creati (è uno dei motivi per cui è così semplice progettare un'applicazione client/server in Java...).

    Per quanto riguarda il passaggio dei parametri con tipi di dato primitivi, invece, si può notare che effettivamente i nuovi parametri sono delle copie. All'interno dei metodi si lavora con delle copie nude e crude dei parametri di partenza.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

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 © 2024 vBulletin Solutions, Inc. All rights reserved.