Autor Tema: Java warning uses unchecked or unsafe operations Recompile with -Xlint CU00678B  (Leído 6417 veces)

RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Mis versiones del Ejercicio propuesto en la Entrega Nº78. Ejercicio CU00678B.

Presento dos códigos a los cuáles llegué luego de muchos tropiezos y muchas relecturas.


El primer código que compila sin Warnings es el siguiente:

Código: [Seleccionar]
import java.util.*;

public class Ejercicio_Polimorfismo{
    // Declaración de los campos de instancia.
    public Ejercicio_Polimorfismo(){ // Constructor de clase
    }
   
    public static void main (String[] args){
        ArrayList<Set> miLista; // Declaración de los objetos.
        HashSet<String> objHashSet;
        TreeSet<Integer> objTreeSet;
       
       
        miLista = new ArrayList<Set>(); // Instanciación de los objetos
        objHashSet = new HashSet<String>();
        objTreeSet = new TreeSet<Integer>();
       
       
        objHashSet.add("Sol"); // Añade elementos al objeto tipo HashSet
        objHashSet.add("Luna");
        objHashSet.add("Saturno");
       
        objTreeSet.add(2); // Añade elementos al objeto tipo TreeSet
        objTreeSet.add(8);
        objTreeSet.add(5);
               
        miLista.add(objHashSet); // Se agrega a la lista el objeto HashSet y el objeto TreeSet
        miLista.add(objTreeSet);

        System.out.print("\f"); // Borra la pantalla
       

        for (Set objetoSet:miLista){ // Se recorre el objeto ArrayList con for each
           
        Iterator itElementos = objetoSet.iterator(); // No se especifica tipo de dato a recorrer
       
            while(itElementos.hasNext()){ // Recorro cada elemento del ArrayList con un iterador
                System.out.println(itElementos.next());
            }
           
        } // fin for each
                     
       
    } // fin main
   
   
} // fin de la clase


En este segundo código aparecen los incómodos Warnings:

Código: [Seleccionar]
import java.util.*;

public class Ejercicio_Polimorfismo2{
    // Declaración de los campos de instancia.
    public Ejercicio_Polimorfismo2(){ // Constructor de clase
    }
   
    public static void main (String[] args){
        ArrayList<Set> miLista; // Declaración de los objetos.
        HashSet<String> objHashSet;
        TreeSet<Integer> objTreeSet;
       
       
        miLista = new ArrayList<Set>(); // Instanciación de los objetos
        objHashSet = new HashSet<String>();
        objTreeSet = new TreeSet<Integer>();
       
       
        objHashSet.add("Sol"); // Añade elementos al objeto tipo HashSet
        objHashSet.add("Luna");
        objHashSet.add("Saturno");
       
        objTreeSet.add(2); // Añade elementos al objeto tipo TreeSet
        objTreeSet.add(8);
        objTreeSet.add(5);
               
        miLista.add(objHashSet); // Se agrega a la lista el objeto HashSet y el objeto TreeSet
        miLista.add(objTreeSet);

        System.out.print("\f"); // Borra la pantalla
       

        for (Set objetoSet:miLista){ // Se recorre el objeto ArrayList con for each
               
            if(objetoSet instanceof HashSet){ // Si el elemento de la lista contiene un objeto HashSet lo recorro con un for each
                for (String tmp:(Set<String>)objetoSet){
                    System.out.println(tmp);
                }
            }
           
            if(objetoSet instanceof TreeSet){ // Si el elemento de la lista contiene un objeto TreeSet lo recorro con un for each
                for (Integer tmp:(Set<Integer>)objetoSet){
                    System.out.println(tmp);
                }
            }
 
                   
        } // fin for each
    } // fin main
} // fin de la clase

Saco como conclusión lo siguiente, y necesitaría ayuda para saber si estoy bien encaminado en las deducciones:

Primer código:

Se usa un for each para recorrer los objetos Set del ArrayList<Set>, y para recorrer esos objetos Set se usa un iterador donde no se especifica el tipo a recorrer. Este "truco" lo vi en un ejercicio del foro y sinceramente inquieta desde algún punto de vista: si bien uno se tranquiliza porque la compilación deja de darnos los warnings luego de machacarnos la cabeza varias horas seguidas, nos surge la inquietante idea de pensar ¿acaso hay cosas que se pueden hacer sin que estén documentadas en el Api de Java? Pues si uno consulta en el Api la interface Iterable:

Interface Iterable<T>

No hay ningún indicio de que <T> sea opcional, sino que interpreto que es obligatorio definir el tipo a recorrer. ¿Cómo se justifica entonces?


Segundo código:

Para el recorrido de los objetos Set se usa un for each, y para recorrer cada uno de esos objetos Set también se usa for each; vale decir que es un for each anidado dentro de otro for each, lo cual estaría bien desde el punto de vista que for each permite recorrer colecciones, y el tipo ArrayList implementa la interface Collection y interface Set tiene como superInterface la interface Collection. De esta manera justificaría poder usar for each en cada recorrido.

Ahora bien: aparecen los warnings. Si bien (yo) estoy seguro que no cometo ningún error de conversión de tipos, cada vez que extraigo del ArrayList<List> un objeto que yo estoy seguro que es un -supongamos- HashSet y lo quiero almacenar en un atributo de tipo HashSet, el compilador me lo va a advertir ya que él (el compilador) en tiempo de compilación no está seguro de que ese objeto Set que estoy extrayendo del ArrayList<List> en verdad sea un HashSet.

¿Es por eso que salta el warnings, verdad?
« Última modificación: 28 de Marzo 2015, 17:42 por Alex Rodríguez »

toni_apr

  • Avanzado
  • ****
  • Mensajes: 497
  • Curiosidad, es uno de los pilares del Conocimiento
    • Ver Perfil
Re:Tutorial CU00678B. Ejercicio de Polimorfismo en Java.
« Respuesta #1 en: 27 de Marzo 2015, 22:14 »
Hola RaGA

He visto tu segunda versión, la que da los warnings. Y después de darle mis vueltas, no sé como eliminarlos.
Espero que alguien que sepa más pueda indicarte.

Por mi parte quiero señalar  que en el enunciado se pide hacer el recorrido con iteradores. Y los iteradores se usan con while.

Si ya has hecho el ejercicio con iteradores y while y quieres probar con for each, bien. Pero si no, pruébalo primero así.

Saludos

RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Re:Tutorial CU00678B. Ejercicio de Polimorfismo en Java.
« Respuesta #2 en: 28 de Marzo 2015, 13:57 »
Muchas gracias toni por dedicarle tiempo y atención a mi codificación. Sinceramente te agradezco lo que me vienes ayudando.
Yendo a este ejercicio en sí, efectiviamente usé un iterador para recorrer cada elemento del ArrayList en el primer código que publiqué, dando cumplimiento a la consigna del ejercicio. Pero claro que con la salvedad de no especificar el tipo de elemento a recorrer, es la única forma que no aparezcan los Warnings. Y por eso mismo también me preguntaba cómo puedo darme cuenta que no es obligatorio declarar el <T> luego de leer la documentación del API: Interface Iterable<T>

Y respecto del segundo código: quise probar de resolver el problema con for each ya que tratándose de colecciones, es aplicable el uso de for each. De ahí que exponía en mi primera publicación de este hilo una esbozo de "posible explicación" de los sucedido.
Soy conciente de mi "rango de novato" y trato de sacar conclusiones de mis experiencias codificando varias veces los ejercicios, de las lecturas de las lecciones, y de los ejercicios y comentarios de los compañeros del foro. Pero recurro como ahora a los más exprimentados para saber si voy por buen camino (y no inventarme un Java de fantasía jeje).

Alex Rodríguez

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2050
    • Ver Perfil
Hola RaGa y toni. RaGa, creo que sí vas por buen camino... la aparición de warnings no siempre debe considerarse negativa. Un warning es un aviso, no un error. En este caso el aviso indica que el comprobador de tipos del compilador no puede garantizar que las operaciones que se hacen con tipos sean seguras (correctas). El comprobador de tipos tiene algoritmos para verificar que los tipos sean correctos, pero esos algoritmos no siempre llegan hasta donde nosotros suponemos que van a llegar. Pero si nosotros como programadores estamos seguros de que estamos haciendo algo correcto no debemos prestarle demasiada atención, en el sentido de que no podemos pensar como un compilador, y en el sentido de que son cuestiones relativamente avanzadas que no comprometen el programa si como dices "yo estoy seguro de que no cometo ningún error de conversión de tipos".

Otra cosa, esta declaración:

        ArrayList<Set> miLista; // Declaración de los objetos.
        HashSet<String> objHashSet;
        TreeSet<Integer> objTreeSet;


Es más adecuada así:

        List<Set> miLista; // Declaración de los objetos.
        Set<String> objHashSet;
        Set<Integer> objTreeSet;

Así hacemos uso del polimorfismo: lo más general (List o Set) luego se implementa en lo más particular, ArrayList, ó TreeSet, HashSet, etc.

Con este código parece que desaparecen los warning, pero a mí no acaba de gustarme:

Código: [Seleccionar]
import java.util.*;

public class Ejercicio_Polimorfismo2{
    // Declaración de los campos de instancia.
    public Ejercicio_Polimorfismo2(){ // Constructor de clase
    }

    public static void main (String[] args){
        List<Set> miLista; // Declaración de los objetos.
        Set<String> objHashSet;
        Set<Integer> objTreeSet;

        miLista = new ArrayList<Set>(); // Instanciación de los objetos
        objHashSet = new HashSet<String>();
        objTreeSet = new TreeSet<Integer>();

        objHashSet.add("Sol"); // Añade elementos al objeto tipo HashSet
        objHashSet.add("Luna");
        objHashSet.add("Saturno");

        objTreeSet.add(2); // Añade elementos al objeto tipo TreeSet
        objTreeSet.add(8);
        objTreeSet.add(5);

        miLista.add(objHashSet); // Se agrega a la lista el objeto HashSet y el objeto TreeSet
        miLista.add(objTreeSet);

        System.out.print("\f"); // Borra la pantalla

        for (Set objetoSet:miLista){ // Se recorre el objeto ArrayList con for each
            if(objetoSet instanceof HashSet){ // Si el elemento de la lista contiene un objeto HashSet lo recorro con un for each
                for (Object tmp:objetoSet){
                    System.out.println(tmp);
                }
            }

            if(objetoSet instanceof TreeSet){ // Si el elemento de la lista contiene un objeto TreeSet lo recorro con un for each
                for (Object tmp:objetoSet){
                    System.out.println(tmp);
                }
            }

        } // fin for each
    } // fin main
} // fin de la clase

Saludos


RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Gracias Alex por venir en nuestro auxilio.
Perfecto entonces, y muy interesante lo que nos revelas acerca de los algoritmos de comprobación de tipos, es como mirar por la rendija la propia cocina del compilador.

Tengo una consulta que me surge respecto de lo que me sugieres cuando dices:

Citar
Otra cosa, esta declaración:

        ArrayList<Set> miLista; // Declaración de los objetos.
        HashSet<String> objHashSet;
        TreeSet<Integer> objTreeSet;


Es más adecuada así:

        List<Set> miLista; // Declaración de los objetos.
        Set<String> objHashSet;
        Set<Integer> objTreeSet;

Entiendo que iré captando y asimilando las bondades y beneficios del polimorfismo conforme vaya avanzando en las posteriores Lecciones y ejercitaciones, pero por lo pronto -y por las comprobaciones que realicé en virtud de tu sugerencia- puedo advertir algo y corrígeme si estoy equivocado.

Al declarar e instanciar el objeto miLista de la siguiente manera:

ArrayList<Set> miLista;
miLista = new ArrayList<Set>;

el objeto miLista podrá usar tanto los métodos correspondientes a la clase ArrayList, como los métodos correspondientes a la interface List, por ser la interface List implementada por la clase ArrayList, cierto?

Ahora bien, si en cambio el objeto miLista fuera declarado e instanciado de la siguiente manera:

List<Set> miLista;
miLista = new ArrayList<Set>;

el objeto miLista podrá usar solo los métodos de la interface Set, pero no los métodos de la clase ArrayList, cierto?.

¿Es correcto lo que digo? A simple vista sería como un "mal negocio" pero sospecho que los beneficios vienen por otro lado que por ahora no visualizo.
Hasta este momento veo como beneficio que un objeto declarado como List podrá recibir como argumento todo objeto cuya clase implemente la interface List (que no es poca cosa).

Alex Rodríguez

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2050
    • Ver Perfil
Hola RaGa, como bien dices irás captando y asimilando el polimorfismo conforme vayas avanzando. De momento puede ser suficiente con tener en cuenta que

List<Set> miLista;
miLista = new ArrayList<Set>;

y

ArrayList<Set> miLista;
miLista = new ArrayList<Set>;

son cosas muy similares, pero la primera hace uso del polimorfismo (miLista pertenece a dos tipos, el tipo List y el tipo ArrayList) y la segunda no. Por tanto la primera forma es una forma más amplia y en principio solo tiene ventajas y no inconvenientes, aunque esto tendrá sus matices pero es preferible seguir avanzando antes que entretenerse en estos detalles ahora.

Saludos

RaGa

  • Moderador Global
  • Intermedio
  • *******
  • APR2.COM
  • Mensajes: 234
    • Ver Perfil
Perfecto, sigo adelante con esas premisas entonces. Muchas gracias.

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".