Pregunta

Puede hacerlo en .NET utilizando la palabra clave " ref " ;. ¿Hay alguna forma de hacerlo en Java?

¿Fue útil?

Solución

¿Qué estás haciendo en tu método? Si simplemente está completando una matriz existente, entonces no necesita una semántica de paso por referencia, ya sea en .NET o en Java. En ambos casos, la referencia se pasará por valor, por lo que la persona que llama podrá ver los cambios en el objeto . Es como decirle a alguien la dirección de su casa y pedirle que le entregue algo, no hay problema.

Si realmente desea semántica de paso por referencia, es decir, la persona que llama verá los cambios realizados en el parámetro en sí, p. configurándolo como nulo o como una referencia a una matriz de bytes diferente, entonces cualquiera de los métodos debe devolver el nuevo valor o debe pasar una referencia a algún tipo de "titular" que contiene una referencia a la matriz de bytes y que puede obtener la referencia (posiblemente modificada) más adelante.

En otras palabras, si su método se ve así:

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

entonces estás bien. Si su método se ve así:

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

entonces necesita cambiarlo a:

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

Para más detalles, lea Parámetro que pasa en C # y Parámetros que pasan en Java . (El primero está mejor escrito que el segundo, me temo. Algún día comenzaré a hacer una actualización).

Otros consejos

En realidad, en Java, las referencias se pasan por valor .

En este caso, la referencia es un objeto byte [] . Cualquier cambio que afecte al objeto en sí se verá desde el método de la persona que llama.

Sin embargo, si intenta reemplazar la referencia, por ejemplo, usando new byte [length] , solo está reemplazando la referencia que obtuvo por paso por valor, por lo que no está cambiando la referencia en el método de la persona que llama.

Aquí hay una lectura interesante sobre este tema: ¡Java es Dam-by-Value Dammit!


Aquí hay un ejemplo 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);
    }
}

Este programa creará una matriz byte de longitud 8 en el método main , que llamará al modifyArray método, donde se crea una nueva matriz byte de longitud 16 .

Puede parecer que al crear una nueva matriz byte en el método modifyArray , la longitud de la matriz byte al regresar al El método main será 16 , sin embargo, ejecutar este programa revela algo diferente:

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

La longitud de la matriz byte al regresar del método modifyArray vuelve a 8 en lugar de 16 .

¿Por qué es eso?

Esto se debe a que el método main llamó al método modifyArray y envió a una referencia copiada al nuevo byte [8] mediante el uso de paso por valor . Luego, el método modifyArray desechó la referencia copiada creando un nuevo byte [16] . Para el momento en que dejamos modifyArray , la referencia al new byte [16] está fuera de alcance (y eventualmente será basura recolectada). Sin embargo, el principal El método todavía tiene referencia al nuevo byte [8] ya que solo envió la referencia copiada y no una referencia real a la referencia.

Eso debería demostrar que Java pasará la referencia usando paso por valor.

Java usa el paso por valor para los argumentos del método .

  • Primitivas (int, boolean, etc. .) son casos especiales en Java ... no objetos per se. En este caso, se pasa una copia de la primitiva (argumento) a la función. Esto se gela bien con la teoría del paso por valor.
  • Para Objetos, lo que sucede es que la referencia al objeto se pasa por valor (se hace una copia de la referencia en lugar del objeto) ... pero ambas referencias apuntan al mismo objeto. Entonces, si modifica un parámetro de objeto en un método, el objeto real se modificará.

Este artículo debería ayudarte. http://www.javaworld.com/ javaworld / javaqa / 2000-05 / 03-qa-0526-pass.html

En cuanto a la pregunta del OP, simplemente pase la referencia a la matriz de bytes [] al método. El resultado neto sería similar a pasar por referencia. Si modifica la matriz de bytes, la persona que llama podrá ver la ejecución del método posterior a los cambios.

Actualización para calmar la resistencia :) = > indica salida

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

Tierra de Java

Modificaciones menores requeridas: Use hashCode () y + para concatenar cadenas en 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  
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top