The Source for Java Technology Collaboration
User: Password:



Felipe Leme

Felipe Leme's Blog

Who let the bugs out?

Posted by felipeal on November 22, 2006 at 05:00 AM | Comments (4)

So, here is the deal. I've created a generic DAO class that looks like the following:

package net.felipeal;

import java.util.ArrayList;

public abstract class DAO<EntityInterface, EntityImpl extends EntityInterface> {
  
  private final Class<EntityImpl> entityClass;
  
  public DAO( final Class<EntityImpl> clazz ) {
    this.entityClass = clazz;
  }

  public List<EntityInterface> getEntities() {
    return getObjects(this.entityClass);
   }

  public <TInterface, TImpl extends TInterface> List<TInterface> getObjects(Class<TImpl> clazz) {
    return new ArrayList<TInterface>();
  }

}
The motivation behind this class is that the sub-classes will have the getEntities() method that would return all entities managed by the DAO, and still have the getObjects() method for other entities. So, for instance, I could have something like:

package net.felipeal;

import java.util.List;

public class ProductDAO extends DAO<Product, ProductImpl> {

  public ProductDAO {
    super(ProductImpl.class);
  }
  
  public static void main(String[] args) {
    final ProductDAO dao = new ProductDAO();
    final List<Product> products = dao.getEntities();
    final List<Customer> customers = dao.getObjects(CustomerImpl.class);
  }

}

The code above works on Eclipse 3.2, but when I try to compile it with javac 1.5.0_09, it fails:

[felipeal@localhost src]$ javac net/felipeal/DAO.java
net/felipeal/DAO.java:15: incompatible types
found   : java.util.List
required: java.util.List
    return getObjects(this.entityClass);
                     ^
1 error

So, looks like one of the two compilers is wrong: either javac should compile that code or (most likely) eclipse should have failed.

I tried a small variation that fails on Eclipse as well:

package net.felipeal;

import java.util.ArrayList;
import java.util.List;

public class DAO<EntityInterface, EntityImpl extends EntityInterface> {
  
  private final Class<EntityImpl> entityClass;
  
  public DAO( final Class<EntityImpl> clazz ) {
    this.entityClass = clazz;
  }

  public List<EntityInterface> getEntities() {
    final List<EntityInterface> list =  getObjects(this.entityClass);
    return list;
   }

  public <TInterface> List<TInterface> getObjects(Class<? extends TInterface> clazz) {
    return new ArrayList<TInterface>();
  }

}
In this class, Eclipse gives a similar error:

Type mismatch: cannot convert from List to List  bug-generics/src/net/felipeal DAOB.java line 15

That makes sense, as I'm using a wildcard and so there is no way to force the returned collection to be an interface implemented by the parameterized argument.

Any clue of what's wrong (with the code, not with the design itself, please :-)? As I'm not a generics expert, I'd like to hear some comments before opening an (possibly invalid) bug on BugParade or Eclipse...

Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Given the parameters you pass to getObjects(), all the compiler can infer is that TInterface is the Object class. When you pass a Class<EntityImpl> to getObjects(), how can the compiler know which parent class of EntityImpl to use for TInterface? You should try to reuse the generic types from the DAO class itself rather than trying to use new ones in this method.

    As a side not, I dropped Eclipse mostly because I ran into several compiler bugs over a couple of months. I'm ready to cope with bugs in almost any situation, but not in a compiler :)

    Posted by: gfx on November 22, 2006 at 05:39 AM

  • This is a dupe of bug #6278587 (Inference broken for subtypes of subtypes of F-bounded types). What a coincidence: I took a look at that bug last night and if every thing checks out, I have a fix already.

    Posted by: peterahe on November 22, 2006 at 08:48 AM

  • By the way, I generally recommend that you use the latter form, see my blog.

    So how do you make it compile? Use explicit type arguments:

    return this.<EntityInterface>getObjects(this.entityClass);

    Posted by: peterahe on November 22, 2006 at 09:53 AM

  • peterahe: Hey cool, thanks for all the information!

    Posted by: gfx on November 22, 2006 at 03:08 PM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds