Search code examples
javagenericsexceptiontype-conversionraw-types

What's the best way to deal with potential runtime exceptions from a java "unchecked conversion"?


So I have a function that looks like this:

@SuppressWarnings("unchecked")
public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz) {
    return new LinkedHashSet<E>( q.getResultList() );
}

What I believe this is doing is taking a javax.persistence.Query and returning its result set as a generic Set<Class>.

This seems like a great solution, but first off, is it actually doing what I think it is, and is this the best way to achieve that? I find it odd that I never reference my clazz param, but it does seem to do what I want it to.

Secondly if this is all correct and sensible, what errors can this throw? I'd imagine if I give it an incorrect class this function wouldn't work, though I'm not sure at all on that.

If I do something like:

Query q = em.createQuery("FROM Element");
Set<Fish> s = MyUtil.getSetOfClass( q, Fish.class);

And if Fish is not a superclass of Element then what happens? Should I assume that this function will always be used correctly or should I be doing so error handling? What are people recommendations of a best practice approach?

Regards,

Glen x


Solution

  • The getSetOfClass does not guarantee that all elements in the Set are objects of type E. If you call it incorrectly (what you always can), like:

     Set<Cat> cats = getSetOfClass(findAllFish(), Cat.class);
    

    you'll receive class cast exceptions at various places later on...

    I'd add some checks to the public getSetOfClass method to guarantee that the content of the set matches the type parameter:

    @SuppressWarnings("unchecked")
    public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz) {
       return getSetOfClass(Query q,Class<E> clazz, true);
    }
    
    @SuppressWarnings("unchecked")
    public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz, boolean validate) {
        List result = q.getResultList();
        if (validate) {
           for (Object o:result) {
              if(!o.getClass().equals(clazz)) {
                  // handle error
              }
           }
        }
        return new LinkedHashSet<E>( result );
    }