Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top