This discussion is archived
12 Replies Latest reply: Sep 20, 2006 1:58 PM by 807569 RSS

Polymorphism weirdness - JDK1.5.0_05

807569 Newbie
Currently Being Moderated
I'm having a strange problem with some code I'm working on: a variable of type List<CustomType> is assigned an object instance of type ArrayList<CustomType>. I can verify in the debugger that this object is an ArrayList. However, when the addAll() method is invoked on this ArrayList (the addAll() adds an ArrayList<CustomType>), AbstractList.add() ends up being called (again, verified in the debugger). Why is Java invoking the base class version? ArrayList has its own implementation of add, and the following code works as expected:
import java.util.ArrayList;
import java.util.List;

public class testList {
    static List l;
    static ArrayList al;
    public static void main(String[] args) {
     l = new ArrayList();
     al = new ArrayList();
     l.add("Q");
     al.add("Brian");
     al = (ArrayList) l;
     al.add("Z");
    }
}
Have I missed some 5.0 weirdness related to the type of CustomType? Is there a known bug?

Brian
  • 1. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    Can you post some code that doesn't work as expected?
  • 2. Re: Polymorphism weirdness - JDK1.5.0_05
    807569 Newbie
    Currently Being Moderated
    This has been modified somewhat, but hopefully gets the point across:
            AServiceInterface asi = (AServiceInterface) super.getService("AService");
            List<CustomDetails> theList =  asi.findCustomDetailsById(theId);
            if(theList == null) {
                theList = new ArrayList();
            }
    
            if (authenticator.isInGroup(ADMIN_GROUP)) {
                theList.addAll(asi.findAllAdminDetails()); // throws UnsupportedOperationException as AbstractList.add() is called
            }
  • 3. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    Okay, well, presumably theList isn't null, as ArrayList wouldn't behave that way. Can we see the code for the list that's returned by findCustomDetailsById?
  • 4. Re: Polymorphism weirdness - JDK1.5.0_05
    807569 Newbie
    Currently Being Moderated
    public List<CustomDetails> findCustomDetailsById (String theId) throws DataAccessException {
        if (StringUtils.isBlank(theId)) {
            return new ArrayList<CustomDetails> ();
        }
    
        List<CustomDetails> theList = dao.getAllById(theId);
    
        for (CustomDetails detail : theList) {
             // fill in details, calls some other DAOs, but returns successfully
        }
    
        return theList;
    }
    And the DAO implementation:
    public List getAllById (String theId) throws DataAccessException {
        return executeQueryAsList(getQuery("theService.find.by.id"), 
            new Object[] {theId},  new CustomDetails [] {new CustomDetails()});
    }
    Brian
  • 5. Re: Polymorphism weirdness - JDK1.5.0_05
    doremifasollatido Journeyer
    Currently Being Moderated
     if(theList == null) {
                theList = new ArrayList();
            }
    You didn't make theList the proper generic type here. Your getAllById doesn't return a proper generic type List, either.
  • 6. Re: Polymorphism weirdness - JDK1.5.0_05
    807569 Newbie
    Currently Being Moderated
    OK I've pushed the code change. <fingerscrossed />

    Is Java really this unpredictable when it comes to mixing parameterized and non-parameterized Collections? It certainly makes upgrading code from 1.4-compliant to 1.5-compliant rather difficult.

    If someone could explain the behaviour I've seen, and why parameterizing the intermediate return values would help, I'd be much obliged :)

    Brian
  • 7. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    Okay, now what about dao.getAllById? If isBlank was true, you'd again have an ArrayList, which would not give that exception. Presumably getAllById returns an unmodifiable list.
  • 8. Re: Polymorphism weirdness - JDK1.5.0_05
    807569 Newbie
    Currently Being Moderated
    Here's the executeQueryAsList. Sorry, didn't realize this was one of my methods ;)
    public List executeQueryAsList (String theQuery, Object [] params, Object [] busObj) throws DataAccessException  {
        Object [] objs = (Object [])super.executeQuery(theQuery, params, busObj);
        if(null != objs && objs.length > 0)
            return Arrays.asList(objs);
        return new ArrayList();
    }
    I don't see that this list is unmodifiable, though it is again unparameterized. Should I just change the declaration to
    public List<E> executeQueryAsList(...) {
    ...
    }
    Brian
  • 9. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    Read the docs for Arrays.asList closely. It says "fixed size." In other words, if you try to add to or delete from that list, you'll get OperationNotSupportedException, or something.
  • 10. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    Parameterization has nothing to do with this, by the way.
  • 11. Re: Polymorphism weirdness - JDK1.5.0_05
    807569 Newbie
    Currently Being Moderated
    Ah, thanks. I just came across the same wording myself. So Arrays.asList() allows me to modify the elements of the Collection, but not to actually add or remove items from it. The fix, then, is to create the ArrayList, iterate through the array, and add each item in turn. And it's nice to know that the parameterization has nothing to do with it. If ArrayList<E> didn't act like ArrayList, it would certainly cause some conceptual problems...

    Brian
  • 12. Re: Polymorphism weirdness - JDK1.5.0_05
    796440 Guru
    Currently Being Moderated
    You can do
    new ArrayList(Arrays.asList(theArray)); 
    .

    It's an additional round of copying, but saves you a line or two of code.