12 Replies Latest reply: Sep 20, 2006 3:58 PM by 807569 RSS

    Polymorphism weirdness - JDK1.5.0_05

    807569
      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
          Can you post some code that doesn't work as expected?
          • 2. Re: Polymorphism weirdness - JDK1.5.0_05
            807569
            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
              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
                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
                   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
                    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
                      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
                        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
                          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
                            Parameterization has nothing to do with this, by the way.
                            • 11. Re: Polymorphism weirdness - JDK1.5.0_05
                              807569
                              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
                                You can do
                                new ArrayList(Arrays.asList(theArray)); 
                                .

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