Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast to generic type (T) gives "unchecked cast" warning

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?

like image 300
Terence Lam Avatar asked Sep 26 '13 15:09

Terence Lam


2 Answers

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.

like image 106
James Dunn Avatar answered Nov 18 '22 20:11

James Dunn


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.

like image 35
Sotirios Delimanolis Avatar answered Nov 18 '22 20:11

Sotirios Delimanolis