java - referenciados - ¿Cómo paso un tipo de datos primitivo por referencia?
tipos de variables en java ejemplos (8)
¿Cómo puedo pasar un tipo primitivo por referencia en java? Por ejemplo, ¿cómo puedo hacer que un int
pasado a un método se pueda modificar?
Eso no es posible en Java
Eso no es posible en Java, como alternativa puede envolverlo en una única matriz de elementos.
void demo() {
int [] a = { 0 };
increment ( a )
}
void increment( int [] v ) {
v[0]++;
}
Pero siempre hay mejores opciones.
Nada en Java se pasa por referencia. Todo pasó por valor.
Editar: tanto las primitivas como los tipos de objetos se pasan por valor. Nunca puede alterar el valor / referencia pasado y esperar que cambie el valor / referencia de origen. Ejemplo:
String a;
int b;
doSomething(a, b);
...
public void doSomething(String myA, int myB) {
// whatever I do to "myA" and "myB" here will never ever ever change
// the "a" and "b"
}
La única forma de evitar este obstáculo, independientemente de que sea una primitiva o referencia, es pasar un objeto contenedor o utilizar el valor devuelto.
Con un titular:
private class MyStringHolder {
String a;
MyStringHolder(String a) {
this.a = a;
}
}
MyStringHolder holdA = new MyStringHolder("something");
public void doSomething(MyStringHolder holder) {
// alter holder.a here and it changes.
}
Con valor de retorno
int b = 42;
b = doSomething(b);
public int doSomething(int b) {
return b + 1;
}
No hay una forma de pasar una primitiva directamente por referencia en Java.
Una solución alternativa es pasar una referencia a una instancia de una clase contenedora, que luego contiene la primitiva como un campo miembro. Tal clase de contenedor podría ser extremadamente simple de escribir para usted:
public class IntRef { public int value; }
Pero, ¿qué hay de algunas clases de envoltura preconstruidas, para que no tengamos que escribir las nuestras? DE ACUERDO:
Las clases Apache commons-lang Mutable *:
Ventajas : Buen rendimiento para un solo uso. Lo completo.
Desventajas : presenta una dependencia de biblioteca de terceros. Sin controles de simultaneidad incorporados.
Clases representativas : MutableBoolean , MutableByte , MutableDouble , MutableFloat , MutableInt , MutableLong , MutableObject , MutableShort .
Las clases de Atomic * de java.util.concurrent.atomic :
Ventajas : Parte de la API estándar de Java (1.5+). Controles de simultaneidad incorporados.
Desventajas : el rendimiento pequeño golpea cuando se utiliza en una configuración de subproceso único. Falta soporte directo para algunos tipos de datos, por ejemplo, no hay AtomicShort.
Clases representativas : AtomicBoolean , AtomicInteger , AtomicLong y AtomicReference .
Nota : Como el usuario ColinD muestra en su respuesta , AtomicReference puede usarse para aproximar algunas de las clases faltantes, por ejemplo, AtomicShort.
Longitud 1 matriz primitiva
La respuesta de OscarRyz demuestra el uso de una matriz de longitud 1 para "envolver" un valor primitivo.
Ventajas : Rápido de escribir. Performant. No se necesita una biblioteca de terceros.
Desventajas : un poco sucio. Sin controles de simultaneidad incorporados. Resultados en un código que no (claramente) se auto-documenta: ¿está la matriz en la firma del método allí para que pueda pasar múltiples valores? ¿O está aquí como andamio para la emulación de paso por referencia?
Ver también
Las respuestas a la pregunta de " Campo booleano mutable en Java ".
Mi opinión
En Java, debe esforzarse por utilizar los enfoques anteriores con moderación o no utilizarlos en absoluto. En C, es común usar el valor de retorno de una función para retransmitir un código de estado (SUCCESS / FAILURE), mientras que la salida real de una función se transmite a través de uno o más parámetros de salida. En Java, es mejor usar Excepciones en lugar de códigos de retorno. Esto libera los valores de retorno del método que se utilizarán para transportar la salida del método real, un patrón de diseño que la mayoría de los programadores de Java consideran más natural que los parámetros externos.
No puedes. Pero puedes devolver un entero que es un valor modificado
int i = 0;
i = doSomething(i);
Si está pasando más de uno, es posible que desee crear un Objeto de transferencia de datos (una clase específicamente para contener un conjunto de variables que se pueden pasar a las clases).
Pase un AtomicInteger
, AtomicBoolean
, etc. en su lugar. No hay uno para cada tipo primitivo, pero puede usar, por ejemplo, una AtomicReference<Short>
si es necesario también.
Tenga en cuenta: rara vez debería haber una necesidad de hacer algo como esto en Java. Cuando quiera hacerlo, le recomiendo que reconsidere lo que está tratando de hacer y vea si no puede hacerlo de otra manera (usando un método que devuelve un int
, por ejemplo ... qué es exactamente lo mejor para do es variará de una situación a otra).
Pase un objeto que tenga ese valor como un campo.
Una opción es usar clases como java.lang.Integer, entonces no estás pasando un primitivo en absoluto.
Por otro lado, puedes usar código como:
int a = 5;
a = func(a);
y tener func devolver el valor modificado.