JAVA. Sobre el cast.

El cast es para realizar conversiones de tipo. Mas que ver su utilidad con los tipos básicos (primitivos) o las referencias, dedico esta entrada a ver cuando compila y cuando no compila. El cast compila siempre que nos movamos hacia abajo por la jerarquia de herencia. Debemos recordar que existe una clase de la que heredan todas (TODAS), excepto los tipos básicos (primitivos) ya que no son objetos, la clase Object.

		Object a;
		int [] v;
		int [][] v2;
		
		a = new int [3];
		v = (int []) a; // compila y correcta.
		a = new int [3];
		v2 = (int [][]) a; // compila y no correcta
		v = (int []) v2; // no compila

Además debemos recordar, que todos los vectores (sea cual sea su dimensión) en JAVA, son objetos que herendan de Object.
La penultima conversión compila, porque nos movemos hacia abajo en la jerarquia, sin embargo, no ejecutará de forma correcta, provocando un error de ejecución.
La última conversión no compila, porque no es correcta y no nos movemos hacia abajo en la jerarquia. int [] no hereda de int [][].

Esquema recursivo con almacen.

Preparando la docencia de DAA me encontre un esquema de programación muy interesante e intuitivo, el esquema recursivo con almacen. Cuando ejecutamos una función recursiva, en ocasiones, dicha función vuelve a resolver problemas para los cuales ya ha calculado la solución. Por ejemplo, en el caso de la serie de Fibonacci:

La funcion recursiva que resuelve esta formula es la siguiente (en C/C++)

int fiboR(int n)
{
   int resultado;

   if(n == 0 || n == 1)
      resultado = 1;
   else
      resultado = f(n-1) + f(n-2);
   
   return resultado;
}

Si realizamos el árbol de llamadas recursivas para f(6) podemos observar que existen subproblemas (llamadas) que se vuelven a resolver (desarrollar).


La idea es crear un vector donde guardamos las soluciones de las llamadas ya realizadas y antes de volver a realizarlas comprobar si dicha llamada ya está resuelta. Si ya está resuelta cogeremos la solución del vector y si no la realizaremos. Obviamente cuando resolvemos una llamada la almacenaremos en el vector de soluciones.

Los pasos a seguir serían:
1. Crear un almacen (vector) con las posibles valores para los cuales resuelvo, n en el caso anterior.
2. Incializarlo a -1.
3. Modificar la función recursiva para que:
3.1 Almacene la solución de la llamada resuelta en el almacén.
3.2 Compruebe antes de realizar una llamada si dicha llamada ya está resuelta en el almacen.

Ahí queda eso… en los próximos dias pondre la solución definitiva. 🙂

JAVA. Vectores y polimorfismo.

Este es un problemilla que me surgió el otro dia al intentar «castear» el Object [] que devuelve una colección.
Observemos el código:

public class TestVectores{
          public static void main(String []args){
        // JAVA permite que el vobj apunte a un vector que contenga
        // elementos de su tipo, o derivados. String deriva de 
        // Object.
        Object [] vobj = new String [] {"uno", "dos", "tres"};
        // Conversion valida, vobj esta apuntando a un vector de 
        // String.
        String [] vcads = (String []) vobj;

        ArrayList  vlists = new ArrayList();
        vlists.add("uno");
        vlists.add("dos");
        vlists.add("tres");

        // La conversión de abajo no funciona.
        Object [] vList = vlists.toArray();
        String [] vcads2 = (String []) vList;
        /* vlist.toArray() devuelve un Object [],
         * pero este no está apuntando a un String [], sino a un
         * Object [] en el que cada posición tiene un String.
         */
        // Algo asi internamente..
        Object [] miArrayList = new Object [3];
        miArrayList[0] = new String("uno");
        miArrayList[1] = new String("dos");
        miArrayList[2] = new String("tres");
        // Por esto la conversión no se puede hacer así
        String [] vcads3 = (String []) miArrayList;
        // hay que hacerla elemento a elemento
         }
}