I have a byte array like this, that I do some operations on like increment and decrement.
byte[] cells = new byte[numCells]
....
....
cells[index] ;
Now, I want to change the type of the array cells based on some user input parameter to byte, short, int or long.
So, I made a new class Cell
public class Cell<T extends Number> {
T cell;
Cell(T defaultValue){
cell = defaultValue;
}
T get(){
return cell;
}
void set(T t){
cell = t;
}
}
And I am trying to use it like this
ArrayList<Cell<?>> cells;
if(cellSize == 8)
cells = new ArrayList<Cell<Byte>>(numCells);
else if(cellSize == 16)
cells = new ArrayList<Cell<Short>>(numCells);
...
...
The compiler throws the following error
error: incompatible types: ArrayList<Cell<Byte>> cannot be converted to ArrayList<Cell<?>>
cells = new ArrayList<Cell<Byte>>(numCells);
^
How can I accomplish this?
CodePudding user response:
You have to obey the covariance/contravariance rules of the language.
ArrayList<Cell<Byte>>
// is not assignable to
ArrayList<Cell<?>>
but:
ArrayList<Cell<Byte>>
// is not assignable to
ArrayList<? extends Cell<?>>
CodePudding user response:
You don't need to decide for your generics on creation time:
List<Cell<?>> cells = new ArrayList<>(10);
cells.add(new Cell(Short.MAX_VALUE));
cells.add(new Cell(Byte.MAX_VALUE));
CodePudding user response:
You'd have to type the variable as ArrayList<? extends Cell<?>>
.
But even if that gets it to compile, it might not help you much. Wildcards are useful as method parameters, otherwise they're mostly a hindrance.
You might want to redesign your code so that the class is used in another class which has a type variable shared with Cell<T>
, such as Table<T>
so you just work with T
inside both classes, and use the actual type in your "main" code when instantiating a Table<Short>
for example.