Ir al contenido principal

Instalando Apache NetBeans 10 y configurarlo con Jakarta EE

¿Por valor o por referencia?

Esta es una pregunta existencial para todo programador Java. Cada uno encuentra una respuesta satisfactoria. Pero ahora veremos, basándonos en el libro para Certificación SCJP 1.5 de Katty Sierra, sobre la respuesta correcta.



Me diréis:  pero ahora estamos en Java 7, casi la 8.. y ese libro habla de una versión antigua. Cierto, pero la esencia de Java no ha cambiado.

Variables por valor

Entendemos como asignación de variables por valor cuando se hace una copia del valor de una variable a otra. Esto lo vemos así:
    public static void main(String[] args) {
        int a = 10; //es una variable
        int b = 20; //es otra variable
        int c = a;  //la variable "c" tiene la copia del valor de "a"
        a = 30; //"a" tiene otro valor
        System.out.format("a=%d, b=%d, c=%d", a, b, c); //imprime a=30, b=20, c=10
    }

Esta asignación también aplica para los parámetros de funciones.
El resultado es:
Valores antes de cambiar
a=10, b=20, c=30
Valores cambiados en el método
a=100, b=200, c=300
Valores después de cambiar
a=10, b=20, c=30

Entonces, estamos claros que, si se asigna otro valor a las variables desde dentro de un método, estos nuevos valores no afectan a las variables originales ¿cierto? Por tanto, estamos casi asegurando de que los parámetros son pasados por valor.

Variables por referencia

¿Qué pasa con los objetos? Revisemos este código:
Entonces... podemos concluir que cuando son objetos, los parámetros son por referencia.. porque hemos demostrado que cuando se cambia el valor desde dentro de un método afecta a la variable original.

Listo, terminó mi apunte, y todos estamos satisfechos ¿Verdad que es bonito haber demostrado que los parámetros de tipo nativo son por valor y los de tipo objeto son por referencia?

¿por qué? Porque el código no es el mismo. Lo que hemos cambiado es valor de una variable que pertenece a otra variable.
Me explico.

En el primer ejemplo, se cambió el valor de la variable directamente.. es decir:
    private static void cambiandoValores(int a, int b, int c) {
        a = 100; //se le asigna un nuevo valor...
        b = 200; //... aquí tambien se le asigna un nuevo valor
        c = 300; //... idem... notemos que es a la misma variable
//....
Por tanto, si fuera con objetos... y para ser más justos... deberíamos cambiar directamente a la variable:
//...
    private static void cambiarNombre(Persona p) {
        p=new Persona(); //aqui se le está asignado un nuevo valor (objeto) al mismo parámetro recibido
        p.setNombre("Santiago"); //y...aqui tendrá otro valor
    }
//...
Entonces, otra sería la historia. Probemos este último código completo:
El resultado será:
El nombre antes del método es:Diego
El nombre en el método es:Santiago
El nombre después del método es:Diego

Es lo más justo, es exacto decir: p=new Persona() luce igual que a=100 Entonces.. los parámetros son por valor o por referencia?

La respuesta es:

Es por valor.. son copias del valor ¿qué guarda la variable de tipo de objeto? Guarda la dirección de la memoria del objeto creado en el heap. No hace diferencia si es tipo nativo o tipo objeto.. siempre es por valor. Kathy Sierra lo describe así en el libro "SCJP Sun Certified Programmer for Java 5 Study Guide"

(Traducción libre:)
"Si Java pasa objetos al pasar la referencia a la variable en su lugar, ¿significa que  Java utiliza el pase por referencia de los objetos? No exactamente, aunque a menudo se escucha y se lee que así lo hace. Realmente, Java  pasa  por  valor todas las variables que se ejecutan en una sola máquina virtual. Pasar por valor significa pasar el valor de la variable. Y eso significa, pasar la copia de la variable! (Hay esa palabra 'copia' de nuevo!)

"No importa si estás pasando una variable primitiva o variables de referencia, siempre estás pasando una copia de los bits de la variable. Así que para una variable primitiva, estás pasando una copia de los bits que representan el valor. Por ejemplo, si se pasa una variable int con el valor de 3, está pasando una copia de los bits que representan 3. La llamada al método obtiene su propia copia del valor, para hacer con ella lo que quiera.

"Y si estás pasando una variable de referencia a objeto, lo que está pasando es una copia de los bits que representan la referencia a un objeto. La llamada al método, entonces, obtiene su propia copia de la variable de referencia, para hacer con ella lo que quiera. Pero debido a que dos variables de referencia idénticas se refieren al mismo objeto, si el método llamado modifica el objeto (mediante la invocación de los métodos setter, por ejemplo), el objeto variable original del llamante ha sido modificado."

Capítulo 3: Asignaciones. Sección "Java usa semánticas por valor?"

Espero que con esto se tenga más claro el uso de las variables en Java.

Con lo expuesto aquí.. la siguiente pregunta es.. ¿Existen punteros en Java?

Que tengan un buen día :)

Actualización (2016-01-08):

Aquí tengo dos ejemplos donde se implementa el mismo ejemplo pero usando los parámetros por valor o por referencia explícitamente. En Pascal se necesita de la instrucción var para que sea por referencia. En C se utiliza con & y *

Comentarios

Entradas más populares de este blog

RESTful... la forma más ligera de hacer WebServices (Parte 1)

Quienes hayan usado SOAP para WebService, sabrán que es bien fácil de diseñar, pero algo complicado de consumir: se necesita toda una API para construir los clientes utilizando el WSDL. Por ejemplo, para PHP se necesita de la biblioteca NuSOAP. Entonces, para lograr el concepto de "lenguaje único XML" es un dolor de cabeza. Y más aún si el cliente es tan simple como JavaScript, manejar XML de SOAP provocaría suicidos masivos... o no usar WebServices.

Además, con SOAP se permite crear un solo servicio y ponerle varios métodos. Esto puede llevar a un mal diseño del servicio ya que podría tener un servicio que haga de todo: por ejemplo, un servicio de manejo de Clientes que permita también manejar Proveedores.

RESTful es una propuesta muy interesante de Roy Fielding que permite manejar los servicios web con métodos definidos, manteniendo la simpleza del protocolo como XML, pero que cada servicio sea identificado únicamente con un solo URI.

En este post veremos cómo crear un Ser…

Contraseñas encriptadas con Java

¿Quién no ha querido encriptar texto o archivo? Hay diversas maneras para hacer eso, por ejemplo, utilizando un diccionario donde se reemplazara cada caracter por un código.. y para poder desencriptarlo se debería utilizar el mismo diccionario para revertir el proceso. Pero si el diccionario cae en manos de alguien que no queremos que lo sepa, entonces estamos en peligro.
Cuando yo programaba en pascal, mi encriptación favorita era invirtiendo los bits... pero cualquiera también puede invertir los bits y listo.
Pero ya gente experta logró algoritmos de encriptación populares. Los más conocidos: MD5 y SHA.
En este post hablaremos cómo encriptar texto, sobretodo las contraseñas, utilizando MD5 o SHA.