Java: ¿Cómo pasar byte por referencia?

Puedes hacerlo en .NET usando la palabra clave “ref”. ¿Hay alguna forma de hacerlo en Java?

¿Qué estás haciendo en tu método? Si simplemente está poblando una matriz existente, entonces no necesita semántica de referencia paso a paso, ya sea en .NET o en Java. En ambos casos, la referencia pasará por valor, de modo 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 quiere semántica de paso por referencia, es decir, la persona que llama verá los cambios realizados en el parámetro en sí, por ejemplo, estableciendo que sea nulo o una referencia a una matriz de bytes diferente, entonces cualquiera de los métodos debe devolver el nuevo valor, o necesita pasar una referencia a algún tipo de “titular” que contiene una referencia a la matriz de bytes, y que puede tener la referencia (posiblemente modificada) tomada posteriormente de ella.

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 necesitas 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 { public T value; // Use a property in real code! } public void createArray(Holder 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ámetro que pasa en Java . (La primera está mejor escrita que la segunda, me temo. Algún día me pondré a hacer una actualización).

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

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

Sin embargo, si intenta reemplazar la referencia, por ejemplo usando un new byte[length] , solo está reemplazando la referencia que obtuvo por el valor de paso por paso, 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 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 progtwig creará una matriz de byte de longitud 8 en el método main , que llamará al método modifyArray , donde se crea una nueva matriz de byte de longitud 16 .

Puede parecer que al crear una nueva matriz de byte en el método modifyArray , la longitud de la matriz de byte al volver al método main será 16 , sin embargo, la ejecución de este progtwig revela algo diferente:

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

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

¿Porqué es eso?

Esto se debe a que el método main llamó al método modifyArray y envió una referencia copiada al new byte[8] utilizando pass-by-value . Luego, el método modifyArray tiró la referencia copiada creando un new byte[16] . En el momento en que modifyArray , la referencia al new byte[16] está fuera del scope (y finalmente será basura). Sin embargo, el método main todavía tiene referencia al new byte[8] ya que solo envió el copiado referencia y no una referencia real a la referencia.

Eso debería demostrar que Java pasará referencia utilizando pass-by-value.

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

  • Los primitivos (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 combina bien con la teoría de pasar 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 de el objeto) … pero ambas referencias apuntan al mismo objeto. Entonces, si modifica un parámetro de objeto en un método, el objeto real será modificado.

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

En cuanto a la pregunta de OP, simplemente pase la referencia a la matriz byte [] 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 los cambios publicar la ejecución del método.

Actualice para sofocar 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

Minors mods reqd: Use hashCode () y + para concat 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 }