4 Replies Latest reply on Feb 17, 2010 10:25 PM by 843793

    Generic & inapplicable arguments

    843793
      I'm reasonably new to generics, and having problems with a simple Factory model and inapplicable arguments. Everything looks fine until I try to call a DAO method. I'm stumped.......here is some test code I am using to get the pattern right.
      public class DAOFactory {
           public static BaseDAO<?> getDAOInstance(String name) {
                if (name.equalsIgnoreCase("item")) { 
                     return new ItemDAO();
                } else if (name.equalsIgnoreCase("country")) {
                     return new CountryDAO();
                }
           }
      }
      
      public abstract class BaseDAO<E> {
           public abstract Long create(E item);
           public abstract E getByRecordID(Long recordID);
      }
      
      public class ItemDAO extends BaseDAO<ItemEntity> {
           @Override
           public Long create(ItemEntity item) {
                return new Long(9);
           }
           @Override
           public ItemEntity getByRecordID(Long recordID) {
                return new ItemEntity();
           }
      }
      
      public class ItemEntity {
      }
      
      public class Test {
           public static void main(String[] args) {
                ItemEntity item = new ItemEntity();
                BaseDAO<?> dao = DAOFactory.getDAOInstance("item");
                dao.create(item);    // error
           }
      }
      Everything is fine until I call dao.create(item) which causes a "Not applicable for the arguments" error message. It expects the method +"public abstract Long create(ItemEntity item)"+ in the BaseDAO.class (rather than +"public abstract Long create(E item);"+ )


      I really don't want to have to put every subclass method in the abstract class. Can anyone explain what is wrong here.

      Thank you, Len
        • 1. Re: Generic & inapplicable arguments
          walterln
          BaseDAO<?> means the type in specific type but unknown. So it could be a BaseDAO<CountryItem> which mean you should not be allowed to call dao.create(new ItemEntity()) as that would give a class cast.

          You probably want:
          public class DAOFactory {
            public static <T> BaseDAO<T> getDAOInstance(Class<T> type) {  .. }
          }
          
          public static void main(String[] args) {
            ItemEntity item = new ItemEntity();
            BaseDAO<ItemEntity> dao = DAOFactory.getDAOInstance(ItemEntity.class);
            dao.create(item);
          }
          
          // might be to use an interface there though
          public class DAOFactory {
            public static <T extends Persistent> BaseDAO<T> getDAOInstance(Class<T> type) {  .. }
          }
          
          public Long create(Persistent object) {
            return DAOFactory.getDAOInstance(object.getClass()).create(object);
          } 
          • 2. Re: Generic & inapplicable arguments
            843793
            Hmm... not sure I follow the second Interface suggestion logic, but on the first suggestion I'm getting a warning in the DAOFactory and as well because I am trying to replace bunches of reflection code, the DAO needs to be dynamic, i.e.
              BaseDAO<?> dao = DAOFactory.getDAOInstance(ItemEntity.class);
              dao.create(new ItemEntity()); // error
            rather than
              BaseDAO<ItemDAO> dao = DAOFactory.getDAOInstance(ItemEntity.class);
              dao.create(new ItemEntity());   // works
            I can probably work around that, but the factory throws a warning on the return cast (which I could suppress but would prefer not to).....
                 public static <T> BaseDAO<T> getDAOInstance(Class<T> type) {
                      
                      if (type.equals(ItemEntity.class)) {
                           return (BaseDAO<T>) new ItemDAO();   // cast warning
            This really is new ground....(but interesting),

            Thanks, Len
            • 3. Re: Generic & inapplicable arguments
              843793
              Here is a pattern that achieves what I need (thanks to earlier posting for the core idea):
              // DAO concerns
              public interface DAO { 
                   public <T extends BaseDAO<?>> T create(Class<T> type);
              }
              
              public class DAOFactory implements DAO {
                   public <T extends BaseDAO<?>> T create(Class<T> type) {
                        try {
                             return type.newInstance();
                        } catch (Exception e) {
                             return null;
                        }
                   }
              
              public class CarDAO implements BaseDAO<Car> {
                   @Override
                   public Long create(Car car) {
                        System.out.println("Created a new car");
                        return new Long(2);
                   }
              }
              
              // Entity concerns
              public interface Entity {
                   public <T extends BaseEntity> T create(Class<T> type);
              }
              
              public class EntityFactory implements Entity {
                   public <T extends BaseEntity> T create(Class<T> type) {
                        try {
                             return type.newInstance();
                        } catch (Exception e) {
                             return null;
                        }
                   }
              }
              
              public class Car implements BaseEntity {
                   public String getName() {
                        return "Aston Martin";
                   }
              }
              
              // Usage
              EntityFactory cf = new EntityFactory();
              Class foo = Class.forName("Car");
              BaseEntity car = cf.create(foo);
              
              DAOFactory ef = new DAOFactory();
              Class bar = Class.forName("CarDAO");
              BaseDAO dao = ef.create(bar);  
              dao.create(car);
              System.out.println(car.getName());
              Len
              • 4. Re: Generic & inapplicable arguments
                843793
                Creo que ahora lo entiendo mucho mejor, mil gracias!!


                Aqui você tem todos os [jogos do mario|http://www.jogos-domario.com/] para você aproveitar como nunca o seu favorito mini [jogos de futebol|http://www.jogos-defutebol.com]. Você pode encontrar informações sobre os [jogos de meninas|http://www.jogos-demeninas.com/], todos juntos en una pagina para que disfrutes como nunca.