4 Replies Latest reply: Sep 16, 2008 7:40 AM by 843793 RSS

    Cast Object to ArrayList with Generics?

    843793
      ArrayList<Employee> employees = (ArrayList<Employee>)request.getSession().getAttribute("employees");
      ...

      gives me this warning:
      Type safety: Unchecked cast from Object to ArrayList<Employee>
      Any idea how I can solve this problem?
        • 1. Re: Cast Object to ArrayList with Generics?
          800329
          JochusH wrote:
          Any idea how I can solve this problem?
          Depends on what you mean with "solving" the problem.
          1. You can either cast to ArrayList<?> and later on cast for each get() on the list.
          2. You can suppress the warning.

          Background: Casting is a runtime check (and some flagging). As the information on Generics will be gone due to erasure, the cast will be to ArrayList<?> anyway. Applying Solution (2), the compiler adds the casts to Employee each time you get one from the list. Solution (1) requires to put these casts explicitly in your code.
          • 2. Re: Cast Object to ArrayList with Generics?
            843793
            Generics and erasure apart, some casting will be necessary anyway, as the session attributes are Objects.
            • 3. Re: Cast Object to ArrayList with Generics?
              843793
              Thnx for your answers guys! Problem solved! :-)
              • 4. Re: Cast Object to ArrayList with Generics?
                843793
                I am still a bit uncertain as to what the approach is recommended when you are using framework code that is required to return Object. Consider the case where I am using a framework class such as Spring's HibernateTemplate. It implements the template pattern that requires that Object is returned. Here is a slightly contrived example of using it:
                          Object logFiles = this.hibernateTemplate.execute(new HibernateCallback(){
                               public Object doInHibernate(Session session)
                                         throws HibernateException, SQLException {
                                    Object logFiles = ... ; // use session to load a List of logfiles 
                                    return logFiles;
                               }});
                Clearly as spring is framework code it can have no idea what I am going to do with the session that it hands me. They have to return Object from the templated method as I could be loading a single domain object, a collection of domain objects or returning a Number type to represent the number of database rows updated.

                If I am going to use that code above to implement a service method such as
                public List<LogFile> listLogFiles(){
                ...
                }
                then to get rid of the compiler warning that my IDE flags up to me I can do the following:
                @SuppressWarnings("unchecked")
                public List<LogFile> listLogFiles(){
                Object logFiles = this.hibernateTemplate.execute(new HibernateCallback(){
                               public Object doInHibernate(Session session)
                                         throws HibernateException, SQLException {
                                    Object logFiles = ... ; // use session to load a List of logfiles 
                                    return logFiles;
                               }});
                return List<LogFile> logFiles;
                }
                or I could do this:
                public List<LogFile> listLogFiles(){
                List<LogFile> logFiles = new ArrayList<LogFile>();
                List<?> execute = (List<?>)this.hibernateTemplate.execute(new HibernateCallback(){
                               public Object doInHibernate(Session session)
                                         throws HibernateException, SQLException {
                                    Object logFiles = ... ; // use session to load a List of logfiles 
                                    return logFiles;
                               }});
                for( Object o : execute ){
                               logFiles.add((LogFile)o);
                }
                return logFiles;
                }
                else I might try this:
                public List<LogFile> listLogFiles(){
                Object logFiles = this.hibernateTemplate.execute(new HibernateCallback(){
                               public Object doInHibernate(Session session)
                                         throws HibernateException, SQLException {
                                    Object logFiles = ... ; // use session to load a List of logfiles 
                                    return logFiles;
                               }});
                return suppressedCast(logFiles);
                }
                @SuppressWarnings("unchecked")
                List<LogFile> suppressedCast( Object o ){
                return (<LogFile>)o;
                }
                Suppressing the warnings on the larger method seems like bad practice as I might later add further code to the method where a warning might have prevented the introduction of a bug. Looping over the collection and casting each element and adding each element appears to be a waste of processor cycles. Breaking out the cast line and suppressing the warning seems a bit contrived. What do other people do for in a case such as this? What is the"textbook" approach?