So here's my code :
public class SetWritable<T extends Writable> implements Writable {
private Class<? extends Writable> valueClass;
private Set<T> values;
public SetWritable(Class<T> valueClass) {
this.valueClass = valueClass;
this.values = new HashSet<T>();
}
public void readFields(DataInput in) throws IOException {
values = new HashSet<T>();
int len = in.readInt();
for (int i = 0; i < len; i++) {
//this line is where I get the warning
//FYI, WritableFactories.newInstance returns an instance of Writable
T value = (T) WritableFactories.newInstance(valueClass);
value.readFields(in);
values.add(value);
}
}
}
What's confusing to me is this : I've asserted that T extends Writable, so why am I getting a warning when I try to cast the Writable to T? And since I know T extends Writable, is it safe to suppress this warning?
You are getting the warning because WritableFactories.newInstance returns a Writable and your T extends Writable, so it might not be a safe cast. However, since you are using Class<T> as your argument to newInstance it is safe to suppress this warning.
It might be better to store valueClass as Class<T> and use Class#cast to cast for you, then you won't have any ugly @SuppressWarnings hanging over your method.
Writable - Jeffrey 2012-04-05 01:25
All T's are Writable, but not all Writables are Ts. So when you cast a Writable to T, it can't be sure that the Writable is actually a T.
For example, imagine there was an S extends Writable. The newInstance might be an S and not a T, but it'd still be Writable -- but casting it to T would give you a ClassCastException.
All T's are Writable, but not all Writables are T's