java - referencia - paso de parámetros a través de la red
Cómo hacer el equivalente de pasar por referencia para primitivas en Java (6)
Hacer una
class PassMeByRef { public int theValue; }
luego pasa una referencia a una instancia de este. Tenga en cuenta que un método que muta el estado a través de sus argumentos es mejor evitarlo, especialmente en código paralelo.
Este código de Java:
public class XYZ {
public static void main(){
int toyNumber = 5;
XYZ temp = new XYZ();
temp.play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
void play(int toyNumber){
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
}
}
dará salida a esto:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 5
En C ++ puedo pasar la variable toyNumber
como pase por referencia para evitar el sombreado, es decir, crear una copia de la misma variable como se muestra a continuación:
void main(){
int toyNumber = 5;
play(toyNumber);
cout << "Toy number in main " << toyNumber << endl;
}
void play(int &toyNumber){
cout << "Toy number in play " << toyNumber << endl;
toyNumber++;
cout << "Toy number in play after increement " << toyNumber << endl;
}
y la salida de C ++ será esta:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 6
Mi pregunta es: ¿Cuál es el código equivalente en Java para obtener el mismo resultado que el código C ++, dado que Java pasa por valor en lugar de pasar por referencia ?
Java no es llamada por referencia , es solo llamada por valor
Pero todas las variables de tipo de objeto son en realidad punteros.
Entonces, si usas un objeto mutable, verás el comportamiento que deseas
public class XYZ {
public static void main(String[] arg) {
StringBuilder toyNumber = new StringBuilder("5");
play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
private static void play(StringBuilder toyNumber) {
System.out.println("Toy number in play " + toyNumber);
toyNumber.append(" + 1");
System.out.println("Toy number in play after increement " + toyNumber);
}
}
Salida de este código:
run:
Toy number in play 5
Toy number in play after increement 5 + 1
Toy number in main 5 + 1
BUILD SUCCESSFUL (total time: 0 seconds)
Puede ver este comportamiento en bibliotecas estándar también. Por ejemplo, Collections.sort (); Collections.shuffle (); Estos métodos no devuelven una nueva lista, sino que la modifican como objeto de argumento.
List<Integer> mutableList = new ArrayList<Integer>();
mutableList.add(1);
mutableList.add(2);
mutableList.add(3);
mutableList.add(4);
mutableList.add(5);
System.out.println(mutableList);
Collections.shuffle(mutableList);
System.out.println(mutableList);
Collections.sort(mutableList);
System.out.println(mutableList);
Salida de este código:
run:
[1, 2, 3, 4, 5]
[3, 4, 1, 5, 2]
[1, 2, 3, 4, 5]
BUILD SUCCESSFUL (total time: 0 seconds)
No puede pasar primitivas por referencia en Java. Todas las variables del tipo de objeto son en realidad punteros, por supuesto, pero los llamamos "referencias", y también siempre se pasan por valor.
En una situación en la que realmente necesita pasar una primitiva por valor, lo que la gente hará a veces es declarar el parámetro como una matriz de tipo primitivo, y luego pasar una matriz de elemento único como argumento. Entonces pasa una referencia int [1], y en el método, puede cambiar el contenido de la matriz.
Para una solución rápida, puede usar AtomicInteger o cualquiera de las variables atómicas que le permitirán cambiar el valor dentro del método utilizando los métodos incorporados. Aquí hay un código de muestra:
import java.util.concurrent.atomic.AtomicInteger;
public class PrimitivePassByReferenceSample {
/**
* @param args
*/
public static void main(String[] args) {
AtomicInteger myNumber = new AtomicInteger(0);
System.out.println("MyNumber before method Call:" + myNumber.get());
PrimitivePassByReferenceSample temp = new PrimitivePassByReferenceSample() ;
temp.changeMyNumber(myNumber);
System.out.println("MyNumber After method Call:" + myNumber.get());
}
void changeMyNumber(AtomicInteger myNumber) {
myNumber.getAndSet(100);
}
}
Salida:
MyNumber before method Call:0
MyNumber After method Call:100
Tienes varias opciones. El que tiene más sentido realmente depende de lo que estás tratando de hacer.
Opción 1: haga que toyNumber sea una variable miembro pública en una clase
class MyToy {
public int toyNumber;
}
luego pasa una referencia a MyToy a tu método.
void play(MyToy toy){
System.out.println("Toy number in play " + toy.toyNumber);
toy.toyNumber++;
System.out.println("Toy number in play after increement " + toy.toyNumber);
}
Opción 2: devolver el valor en lugar de pasar por referencia
int play(int toyNumber){
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
return toyNumber
}
Esta elección requeriría un pequeño cambio al callsite en main para que se lea, toyNumber = temp.play(toyNumber);
.
Opción 3: convertirlo en una clase o variable estática
Si las dos funciones son métodos en la misma clase o instancia de clase, puede convertir toyNumber en una variable de miembro de clase.
Opción 4: cree una única matriz de elementos de tipo int y pase esa
Esto se considera un truco, pero a veces se emplea para devolver valores de invocaciones de clase en línea.
void play(int [] toyNumber){
System.out.println("Toy number in play " + toyNumber[0]);
toyNumber[0]++;
System.out.println("Toy number in play after increement " + toyNumber[0]);
}
public static void main(String[] args) {
int[] toyNumber = new int[] {5};
NewClass temp = new NewClass();
temp.play(toyNumber);
System.out.println("Toy number in main " + toyNumber[0]);
}
void play(int[] toyNumber){
System.out.println("Toy number in play " + toyNumber[0]);
toyNumber[0]++;
System.out.println("Toy number in play after increement " + toyNumber[0]);
}