Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

jueves, 16 de octubre de 2025

Ejemplo práctico de las diferencias entre variables recibidas por Referencia y por Valor en Java

Esta prueba la hice en java 11 y 17. Se basa en crear un ArrayList cuyos elementos son arrays, para estos ejemplos estoy usando IntelliJ:

public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};

List<String[]> unaListaDeArrays = new ArrayList<>();

unaListaDeArrays.add(unArray);

unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";

unaListaDeArrays.add(unArray);

for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}

System.exit(0);
}
}

Como los arrays son almacenados en el ArrayList por referencia (es decir que lo que se guarda no es el array, es su dirección de memoria) el resultado es:

He perdido a los presentadores y al productor de 31 Minutos y me he quedado sólo con los cantantes. Esto no puede ser. Si se almacenara por valor, el arrayList recibiría una copia de los arrays de forma automática, pero por diseño de la JVM no es así.

Para resolverlo hay que crear una copia del array unArray en memoria antes de añadirlo al arrayList, esto es muy fácil de hacer, una forma es usando el operador "new":

public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};

List<String[]> unaListaDeArrays = new ArrayList<>();

unaListaDeArrays.add(unArray);

unArray = new String[] {"Cucky", "Joe Pino", "Horacio", "Pepe Lota"};

unaListaDeArrays.add(unArray);

for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}

System.exit(0);
}
}

Ya quedó bien:


Otra forma es usando la función clone() que poseen las variables que heredan de la clase Object como la clase String, esta función devuelve una copia del objeto:

public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};

List<String[]> unaListaDeArrays = new ArrayList<>();

unaListaDeArrays.add(unArray.clone());

unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";

unaListaDeArrays.add(unArray.clone());

for (int i = 1; i < unaListaDeArrays.size(); i++) {
for (String s : unaListaDeArrays.get(i))
System.out.println(s + ", ");
}

System.exit(0);
}
}

El resultado es:


En mi caso tuve que usar el segundo método porque los valores del array de string eran devueltos por otra función y la longitud podía variar.

Hora de arreglar esos dos bucles anidados del final, para eso se pueden usar los streams de Java:

public class Main {
public static void main(String[] args) {
String[] unArray = new String[] {"Tulio", "Bodoque", "Patana", "Juanin"};

List<String[]> unaListaDeArrays = new ArrayList<>();

unaListaDeArrays.add(unArray.clone());

unArray[0] = "Cucky";
unArray[1] = "Joe Pino";
unArray[2] = "Horacio";
unArray[3] = "Pepe Lota";

unaListaDeArrays.add(unArray.clone());

unaListaDeArrays.stream().forEach(arr ->
Arrays.stream(arr).forEach(s -> System.out.println(s + ", "))
);

System.exit(0);
}
}


Resultado:




31 Minutos en el Tiny Desk de NPR

No hay comentarios: