Question

Vous pouvez le faire dans .NET en utilisant le mot-clé "ref". Est-il possible de le faire en Java?

Était-ce utile?

La solution

Que faites-vous dans votre méthode? Si vous ne faites que remplir un tableau existant, vous n'avez pas besoin de la sémantique de référence par référence, ni en .NET ni en Java. Dans les deux cas, la référence sera passée par valeur - ainsi, les modifications apportées à l'objet seront visibles par l'appelant. C'est comme dire à quelqu'un l'adresse de votre maison et lui demander de lui livrer quelque chose - pas de problème.

Si vous voulez vraiment choisir une sémantique passe par référence, l'appelant verra si le paramètre lui-même est modifié, par exemple. en lui attribuant la valeur null ou une référence à un tableau d'octets différent, l'une ou l'autre méthode doit renvoyer la nouvelle valeur ou vous devez passer une référence à une sorte de "détenteur". qui contient une référence au tableau d'octets, et qui peut avoir la référence (éventuellement modifiée) récupérée ultérieurement.

En d'autres termes, si votre méthode ressemble à ceci:

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

alors vous allez bien. Si votre méthode ressemble à ceci:

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;
    }
}

alors vous devez le changer en:

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

ou:

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;
    }
}

Pour plus d'informations, consultez les paramètres passés en C # et Paramètre transmis en Java . Je crains fort que le premier ne soit mieux écrit que le dernier. Un jour, je me ferai un plaisir de faire le point.

Autres conseils

En réalité, en Java, les références sont passées par valeur .

Dans ce cas, la référence est un objet byte [] . Toute modification affectant l'objet lui-même sera visible à partir de la méthode de l'appelant.

Cependant, si vous essayez de remplacer la référence, par exemple en utilisant nouvel octet [longueur] , vous ne remplacez que la référence obtenue par la valeur au passage. Par conséquent, vous ne modifiez pas la référence dans la méthode de l'appelant.

Voici une lecture intéressante sur ce problème: Java est un passe-passe sacré!

Voici un exemple concret:

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);
    }
}

Ce programme créera un tableau octet de longueur 8 dans la méthode main , qui appellera le modifyArray , où le nouveau tableau octet de longueur 16 est créé.

Il peut sembler qu'en créant un nouveau tableau octet dans la méthode modifyArray , la longueur du tableau octet lors du renvoi à la La méthode main sera 16 . Cependant, l'exécution de ce programme révèle quelque chose de différent:

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

La longueur du tableau octet lors du retour de la méthode modifyArray revient à 8 au lieu de 16 .

Pourquoi est-ce?

En effet, la méthode main appelée méthode modifyArray a envoyé à une référence copiée au nouvel octet [8] en utilisant valeur par passage . Ensuite, la méthode modifyArray a jeté la référence copiée en créant un nouvel octet [16] . Au moment où nous quittons modifyArray , la référence au nouvel octet [16] est hors de portée (et sera éventuellement détruite.) Cependant, l'élément principal La méthode a toujours une référence au nouvel octet [8] car elle a seulement envoyé la référence copiée et non une référence réelle à la référence.

Cela devrait démontrer que Java transmettra une référence à l'aide d'une méthode de définition donnée.

Java utilise la valeur de passage pour les arguments de méthode .

  • Primitives (int, booléen, etc. .) sont des cas particuliers en Java .. pas des objets en soi. Dans ce cas, une copie de la primitive (argument) est transmise à la fonction. Cela se marie bien avec la théorie du passage par la valeur.
  • Pour les objets, la référence à l'objet est passée par valeur (une copie de la référence est créée plutôt que de l'objet) ... mais les deux références pointent sur le même objet. Donc, si vous modifiez un paramètre d'objet dans une méthode, l'objet réel sera modifié.

Cet article devrait vous aider. http://www.javaworld.com/ javaworld / javaqa / 2000-05 / 03-qa-0526-pass.html

En ce qui concerne la question du PO, transmettez simplement la référence au tableau byte [] à la méthode. Le résultat net serait similaire à passer par référence. Si vous modifiez le tableau d'octets, l'appelant sera en mesure de voir les modifications après l'exécution de la méthode.

Mise à jour pour réprimer la résistance:) = > indique la sortie

Terre .NET

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 mineurs requis: Utilisez hashCode () et + pour concaténer des chaînes dans 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  
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top