Domanda

Puoi farlo in .NET usando la parola chiave " ref " ;. C'è un modo per farlo in Java?

È stato utile?

Soluzione

Cosa stai facendo nel tuo metodo? Se stai semplicemente popolando un array esistente, non hai bisogno della semantica pass-by-reference - sia in .NET che in Java. In entrambi i casi, il riferimento verrà passato per valore, quindi le modifiche all'oggetto saranno visibili al chiamante. È come dire a qualcuno l'indirizzo di casa tua e chiedere loro di consegnargli qualcosa - nessun problema.

Se veramente desideri una semantica pass-by-reference, ovvero il chiamante vedrà tutte le modifiche apportate al parametro stesso, ad es. impostandolo su null o su un riferimento a un array di byte diverso, entrambi i metodi devono restituire il nuovo valore oppure è necessario passare un riferimento a una sorta di "titolare" che contiene un riferimento all'array di byte e che può essere acquisito in seguito dal riferimento (eventualmente modificato).

In altre parole, se il tuo metodo è simile a questo:

public void doSomething(byte[] data)
{
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
}

allora stai bene. Se il tuo metodo è simile al seguente:

public void createArray(byte[] data, int length)
{
    // Eek! Change to parameter won't get seen by caller
    data = new byte[length]; 
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
}

quindi è necessario modificarlo in:

public byte[] createArray(int length)
{
    byte[] data = new byte[length]; 
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
    return data;
}

o

public class Holder<T>
{
    public T value; // Use a property in real code!
}

public void createArray(Holder<byte[]> holder, int length)
{
    holder.value = new byte[length]; 
    for (int i=0; i < length; i++)
    {
        holder.value[i] = (byte) i;
    }
}

Per maggiori dettagli, leggi Parametro che passa in C # e Parametro che passa in Java . (Il primo è scritto meglio del secondo, temo. Un giorno mi metto in giro per fare un aggiornamento.)

Altri suggerimenti

In realtà, in Java, i riferimenti sono passati per valore .

In questo caso, il riferimento è un oggetto byte [] . Eventuali modifiche che interessano l'oggetto stesso verranno visualizzate dal metodo chiamante.

Tuttavia, se si tenta di sostituire il riferimento, ad esempio utilizzando new byte [lunghezza] , si sostituisce solo il riferimento ottenuto per valore pass-by, quindi non si sta cambiando il riferimento nel metodo chiamante.

Ecco una lettura interessante su questo problema: Java è un valore pass-by-value!


Ecco un esempio concreto:

public class PassByValue
{
    public static void modifyArray(byte[] array)
    {
        System.out.println("Method Entry:  Length: " + array.length);
        array = new byte[16];
        System.out.println("Method Exit:   Length: " + array.length);
    }

    public static void main(String[] args)
    {
        byte[] array = new byte[8];
        System.out.println("Before Method: Length: " + array.length);
        modifyArray(array);
        System.out.println("After Method:  Length: " + array.length);
    }
}

Questo programma creerà un byte di lunghezza 8 nel metodo main , che chiamerà editArray metodo, in cui viene creato un nuovo array byte di lunghezza 16 .

Potrebbe sembrare che creando un nuovo array byte nel metodo editArray , che la lunghezza dell'array byte al ritorno al Il metodo main sarà 16 , tuttavia, l'esecuzione di questo programma rivela qualcosa di diverso:

Before Method: Length: 8
Method Entry:  Length: 8
Method Exit:   Length: 16
After Method:  Length: 8

La lunghezza dell'array byte al ritorno dal metodo editArray ritorna a 8 anziché 16 .

Perché?

Questo perché il metodo main ha chiamato il metodo editArray e ha inviato un riferimento copiato al new byte [8] utilizzando pass-by-value . Quindi, il metodo changeArray ha eliminato il riferimento copiato creando un nuovo byte [16] . Quando lasciamo editArray , il riferimento al new byte [16] non rientra nell'ambito di applicazione (e alla fine verrà spazzato via.) Tuttavia, il main fa ancora riferimento al nuovo byte [8] poiché solo ha inviato il riferimento copiato e non un riferimento effettivo al riferimento.

Ciò dovrebbe dimostrare che Java passerà il riferimento usando il valore pass-by.

Java utilizza il valore passa per valore per gli argomenti del metodo .

  • Primitives (int, boolean, ecc. .) sono casi speciali in Java .. non oggetti di per sé. In questo caso, una copia della primitiva (argomento) viene passata nella funzione. Questo si gelifica bene con la teoria del passaggio per valore.
  • Per Oggetti, ciò che accade è che il riferimento all'oggetto viene passato per valore (viene fatta una copia del riferimento anziché l'oggetto) ... ma entrambi i riferimenti puntano allo stesso oggetto. Pertanto, se si modifica un parametro oggetto in un metodo, l'oggetto reale verrà modificato.

Questo articolo dovrebbe aiutarti .. http://www.javaworld.com/ JavaWorld / javaqa / 2000-05 / 03-qa-0526-pass.html

Per quanto riguarda la domanda dell'OP, basta passare il riferimento all'array byte [] al metodo. Il risultato netto sarebbe simile al passaggio per riferimento. Se si modifica l'array di byte, il chiamante sarà in grado di vedere le modifiche dopo l'esecuzione del metodo.

Aggiorna per reprimere la resistenza :) = > indica l'output

.NET Land

class Counter
{
  private int m_count = 0;
  public override string  ToString()
  {
     return String.Format("Counter ID{0} : Value {1}", this.GetHashCode(), m_count);
  }
  public void Increment()
  {  m_count++;  }
}
class MakeAPass
{
   public void PassByValueAndModify(int i)
   {   i = 20;    }

   public void PassByRefAndModify(ref int i)
   {   i = 20;   }

   public void PassByValueAndModify(Counter c)
   {   c.Increment();   }

   public void PassByRefAndModify(ref Counter c)
   {   c.Increment();   }

   public void PassByRefAndReassign(ref Counter c)
   {
      c = new Counter();
      for (int i=0; i<5; ++i)
         c.Increment();
   }
}

static void Main(string[] args)
{
   MakeAPass obj = new MakeAPass();
   int intVal = 10;
   obj.PassByValueAndModify(intVal);
   Console.WriteLine(intVal);              // => 10
   obj.PassByRefAndModify(ref intVal);
   Console.WriteLine(intVal);              // => 20

   Counter obCounter = new Counter();
   obj.PassByValueAndModify(obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID58225482 : Value 1
   obj.PassByRefAndModify(ref obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID58225482 : Value 2
   obj.PassByRefAndReassign(ref obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID54267293 : Value 5
}

Java Land

Mods minori reqd: usa hashCode () e + per concatenare le stringhe in Counter.java ...

class MakeAPass
{
   public void PassByValueAndModify(int i)
   {   i = 20;   }

   // can't be done.. Use Integer class which wraps primitive
   //public void PassByRefAndModify(ref int i)

   public void PassByValueAndModify(Counter c)
   {   c.Increment();   }

   // same as above. no ref keyword though
   //public void PassByRefAndModify(ref Counter c)

   // this can't be done as in .net
   //public void PassByRefAndReassign(ref Counter c)
   public void PassAndReassign(Counter c)
   {
      c = new Counter();
      for (int i=0; i<5; ++i)
         c.Increment();
   }
}
public static void main(String args[])
{
   MakeAPass obj = new MakeAPass();
   int intVal = 10;
   obj.PassByValueAndModify(intVal);
   System.out.println(intVal);                 // => 10 
   //obj.PassByRefAndModify(ref intVal);
   //System.out.println(intVal);               // can't get it to say 20

   Counter obCounter = new Counter();
   obj.PassByValueAndModify(obCounter);
   System.out.println(obCounter.ToString());    // => Counter ID3541984 : Value 1
   //obj.PassByRefAndModify(ref obCounter);
   //Console.WriteLine(obCounter.ToString());   // no ref. but can make it 2 by repeating prev call
   obj.PassAndReassign(obCounter);
   System.out.println(obCounter.ToString());    // => Counter ID3541984 : Value 1
                                                // can't get it to say 5  
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top