This is an Android app, but presumably it happens the same in Java. I have a type LevelFactory from which I derive Level1Factory, Level2Factory, etc. I want to have an array of these classes so I can instantiate a level given the array index.
I can just have a Class[] and put them in that and then just cast them to LevelFactory when I need to use them, but I was wondering what the proper thing to do is.
This is obviously an error “Incompatible types”:
new Class<LevelFactory>[] {Level1Factory.class,Level2Factory.class};
However, I was surprised to see that this is also an error “Generic array creation”:
new Class<? extends LevelFactory>[] {Level1Factory.class,Level2Factory.class};
The following works, but it gives the “Unchecked assignment” warning when assigned to a variable:
new Class[] {Level1Factory.class,Level2Factory.class};
The last is the only option I can get to work. I just ignore the warning, but I would like to do it using generics if that’s actually possible.
Two questions:
Do you really need an Array? Arrays don’t work great with generics. So an
ArrayList<LevelFactory>might be the better solutionDo you really need the downcast to the special type (Level1Factory, Level2Factory)? If they have a common super method which is defined in
LevelFactory(lets sayLevel getLevel()) you should not need to downcast them. Just callgetLevel()and you get the correct Level instance from your factory.Another note because this seems to be a common pitfall:
new Class<? extends LevelFactory>This is not a valid statement (it does not matter if its an array or not).
<? extends T>is only valid for the type on the left side. It defines that the generic type of the created Object can be T or derived from T. For Collections this does not mean that they can store objects of T or derived from T (which can a Collections of T anyway).List<LevelFactory> list = new ArrayList<LevelFactory>()This means you can add objects of LevelFactory, Level1Factory and Level2Factory tolist. When you want to receive objects fromlistthey are of typeLevelFactory.List<? extends LevelFactory> list = new ArrayList<LevelFactory>()Means you can receive objects ofLevelFactoryfromlist. BUT you cannot add any object tolistin a typesafe way because you don’t know the exact generic type oflist. That because you can also assignnew ArrayList<Level1Factory>()tolist. Which means that you can’t even addLevelFactoryobjects tolistbecause they don’t implementLevel1Factory.In general
<? extends Something>on collections is not what you want in most cases.