2

tl;dr: How do I cast an object with type parameters without incurring an 'unchecked cast' warning? i.e:

List<Foo> bar = (List<Foo>) obj;

The compiler is giving me an 'unchecked cast' warning about the following code. How do I fix the warning? Placing a @SuppressWarnings("unchecked") before the cast would represent the saddest of solutions.

public class Container<V> {
    public V getV();

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Container<V> other = (Container<V>) obj;
        return this.getV().equals(other.getV());
    }
}
user121330
  • 199
  • 1
  • 10
  • Related, but not exactly a duplicate: http://stackoverflow.com/q/4169806/1639625 – tobias_k Mar 10 '15 at 22:26
  • 1
    Watch out, objects can be of different class but still be equal. – m0skit0 Mar 10 '15 at 22:26
  • I'm out of flags, but I think it's a duplicate: http://stackoverflow.com/questions/509076/how-do-i-address-unchecked-cast-warnings – dbank Mar 10 '15 at 22:27
  • The problem is `obj` might neither be a `Container>` nor might it be a `Container`. You could if (obj instanceof Container>) Object v = (Container>obj).getV(); if (v instanceof V) V other = (V)v; – eckes Mar 10 '15 at 22:34
  • @dbank Oops! Looks like I gotcha with that tl;dr – user121330 Mar 10 '15 at 22:35
  • @m0skit0 They may or may not - lots of controversy on that one... Not sure it relates to the question at hand. – user121330 Mar 10 '15 at 22:37
  • There's no controversy. This is related to the logic of the program in question. If only one might then your implementation is wrong. Of course it is related to the question, I'm telling you your code is wrong, that `equals` method cannot be used as a generic container. – m0skit0 Mar 10 '15 at 23:10
  • @m0skit0 The snippet is clearly illustrative in context. `List` and `Set` are both instances of `Collection`, but a `List` can never equal a `Set`. You surely see the travesty of an equals method that throws an exception instead of returning false. FYI, if a poster can alter the class by adding one word to render your objections moot, and your objections don't relate to the question, it is categorically unrelated. `public final class ...`, `public class Foo ...`, etc... – user121330 Mar 23 '15 at 17:42

1 Answers1

3

You don't need to cast it to a Container<V>. You can't cast it to a Container<V> without an unchecked cast warning anyway, because it could be a Container of anything.

But when you defer to equals on the V that results from getV, equals will do its own type checking (or it should).

You only need to cast it to Container<?>; let the equals method you call ensure that the other's object is equal to your own object's V.

Container<?> other = (Container<?>) obj;
rgettman
  • 176,041
  • 30
  • 275
  • 357