20 septiembre 2005

Los punteros de java

Hay un par de ideas sobre java muy extendidas: java no tiene punteros y en java todo se pasa por referencia.

La realidad, es que java se entiende mucho mejor si lo pensamos exactamente al revés. En java sólo hay punteros (con excepción de los tipos primitivos) y en java todo se pasa por valor (por copia).

Por ejemplo, en C++ hacemos esto

MiClase a;

y ya está todo correcto. La variable a está perfectamente inicializada. Si en java hacemos eso, tenemos una variable a sin inicializar. Es necesario hacerle un new, exactamente igual que un puntero en C++

MiClase a = new MiClase(); // Esto en Java
MiClase *a = new MiClase(); // Esto en C++

// o este otro tipo de inicialización extrañamente parecida ...

MiClase a = null; // en java
MiClase *a=NULL; // en C++

La única diferencia es la notación con el asterisco. Si pensamos que en java TODO son punteros, no es necesario poner el asterisco para distinguir lo que es puntero de lo que no lo es, por lo que símplemente lo han quitado.

Ahora imaginemos un método que recibe una clase y que le hacemos una llamada

// en java...
void medodo (MiClase a)
{
a = new MiClase();
}
...
MiClase b = null;
metodo (b);

Bueno, pues cuando salimos del método b sigue valiendo null, "apuntando a null". Eso quiere decir que a y b son variables disintas, es decir, se ha pasado la variable b por valor al método.

¿Cómo podemos crear una nueva instancia y devolverla?. En java no queda más remedio que hacerlo en el return, es imposible hacerlo a través de parámetros. Sin embargo, en C++ tenemos más posibilidades. Podemos usar un puntero al puntero, es decir, hacer esto

void metodo (MiClase **a)
{
*a = new MiClase();
}
...
MiClase *b=NULL;
metodo (&b);

o bien, incluso usar referencias de verdad

// El & en la declaración es lo que hace que realmente sea una referencia.
void metodo (MiClase * &a)
{
a=new MiClase();
}
...
MiClase *b=NULL;
metodo (b);
// Aqui b apunta al MiClase creado dentro del método.

Haciéndolo así, el puntero b de fuera del método y el puntero a del parámetro son exactamente la misma variable. Ojo, no quiero decir que sean dos punteros distintos que apunten al mismo lado, sino que son realmente el mismo puntero. Cuando hacemos que a apunte a otro sitio, b también apuntará al mismo sitio. Esto es lo que yo entiendo realmente por referencia.

Vemos en este sentido que C++ nos da más posiblidades que java.

1 comentario:

Anónimo dijo...

Gracias, un poco mas claro.