Search code examples
javaarraylistextend

Implementing ArrayList<ContainedObject> where ContainedObject supports getContainningArrayList()


I have a class ContainedObject which instances are supposed to be contained in an ArrayList.

public class ContainedObject {
    private ContainerArrayList<ContainedObject> containningArrayList;
    public ContainerArrayList<ContainedObject> getContainningArrayList() {
        return containningArrayList;
    }
    public void setContainningArrayList(ContainerArrayList<ContainedObject> list) {
        containningArrayList = list;
    }
}

Now, I want to extend ArrayList in such a way that getContainningArrayList() of it's contained objects will reflect their "container". For example, I override add() this way:

public class ContainerArrayList<ContainedObject> extends ArrayList<ContainedObject> {
    @Override
    public boolean add(ContainedObject e) {
        e.setContainningArrayList(this);
        return super.add(e);
    }
}

So far so good. The thing is, I want to be able to also call ContainerArrayList copy constructor and clone methods, etc, and maintain the same containment reflection. So my question is - should I re implement each of these methods, or do they in some way call each other (i.e. ArrayList(ArrayList) uses add to construct the new arraylist).

Any leads?


Solution

  • If you want the described behavior you have to override clone method or create a custom constructor (or both) taking Collection as an argument. Using the default methods would make your custom objects point to old containningArrayList.

    You can see how things work in ArrayList source code:

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        size = elementData.length;
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }
    
    public Object clone() {
        try {
            @SuppressWarnings("unchecked")
            ArrayList<E> v = (ArrayList<E>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError();
        }
    }
    //Arrays.copyOf returns a copy of the original array, truncated or padded with nulls to obtain the specified length
    

    Also consider turning ContainedObject to interface.