问题
I got a small problem here regarding generics bounded type with lists. Please help out!
Model.java
public class Model {
}
ClassA.java
public class ClassA<T extends Model> {
private List<T> models;
public ClassA() {
models.add((T) new Model());
}
}
It gives me an unchecked cast from Model to T warning on this line:
models.add((T) new Model());
I understand I'm getting this warning because all I can safely cast from a sub class into a super class but not the other way round.
Is there any way to get over this problem or can I just safely supress the warning?
回答1:
You can't do what you're trying to do.
Since T is a subclass of Model:
- every T is a Model
- but not every Model is a T.
Specifically:
If you construct a new Model by calling new Model(), the instance is exactly a Model and not an instance of any subclass.
Where Subclass extends Superclass, you can never successfully do this:
(Subclass) new Superclass();
Because of this, you can not successfully cast a new Model to an instance of T.
The compiler will just give you a warning which you can either ignore or suppress, but you'll get a ClassCastException when you run your program and call the add() method.
回答2:
Take this example
public static void main(String[] args) {
ClassA<SubModel> models = new ClassA<>();
for (SubModel model : models.getModels()){
model.run(); // runtime ClassCastException
}
}
public static class ClassA<T extends Model> {
private List<T> models = new LinkedList<>();
public ClassA() {
models.add((T)new Model()); // compiles and warns
}
public List<T> getModels() {
return models;
}
}
public static class SubModel extends Model {
public void run() {
System.out.println(this);
}
}
public static class Model {
}
The object you've added to models
is of runtime type Model
, which doesn't have a run()
method.
When you eventually try to use the object as an object of type SubModel
, you'll get a ClassCastException
as I do in the main()
method.
You really shouldn't do this, ie. add parent type objects to possible suptype type objects.
回答3:
You need to initialize the list before adding elements in your constructor. I think you you might have copied only the relavant code snippet and thats why it was left out.
Also, I think the only way is to suppress warnings. More info only covariance, contravariance here : Covariance, Invariance and Contravariance explained in plain English?
来源:https://stackoverflow.com/questions/19032215/cast-to-generic-type-t-gives-unchecked-cast-warning