Make B1 and B2 to implement the same interface as B (maybe even empty), and then declare a list <B> instead. You can add and remove members without problems.
The main problem with direct inheritance can be summarized as:
class B1 {}; class B2 extends B1{}; ArrayList<B2> list; addMembers(list);
Here we declare list B2 and pass it as a parameter to the method that list B1 expects. Since every B2 is also B1, it is kind of intuitive that this should work. But now, in this method, it is becoming legal to add also B1 to the transferred list. The collection will be broken when the method returns containing member B1, which is not allowed by the declaration.
To prevent this, the compiler will not allow addMembers to be addMembers with a "compatible inherited type" collection. I found this to be a rather unpleasant limitation that can be easily circumvented using the interfaces as suggested. It is quite difficult to get this right also with the help of wildcards. Do you think you can just write ? extends B1 ? extends B1 ?
void test() { ArrayList<? extends B1> list = new ArrayList(); list.add(new B1());
That I say, these wildcards are not worth the pain. And you can also write ArrayList<? extends java.lang.Object> ArrayList<? extends java.lang.Object> or even ArrayList< ? > ArrayList< ? > will not be useful, such ads still do read-only collection.
Therefore, I would say better
interface B {}; class B1 implements B {}; class B2 extends B1 implements B {}; ArrayList<B> list = new ArrayList<B>(); list.add(new B1()); list.add(new B2()); test2(list); void test2(ArrayList<B> list) { list.add(new B1()); }
source share