I want to create DataSets for use in algorithm testing.
I have a generic wrapper class that holds data of type T as well as information about the arbitrary size/complicatedness of the dataset to be able to map input-size to runtime.
Since not everything I want to test on will simply be multiples of something, I do not want to constrain T.
However I'd like to have a constructor that 'recognizes' something as a Collection and can then infer the size itself.
Below code does work, but has a compiler warning for a good reason or needs to throw an Exception respectively.
public class DataSet<T> {
private final long size;
private final T data;
public DataSet(T data, long size) {
this.data = data;
this.size = size;
}
public <I extends Collection<?>> DataSet(I input) { //allows for DataSet<String> foo = new DataSet(List.<Integer>of(1, 4, 6);
this.data = (T) input; //compiler warning / ClassCastException: unchecked cast I to T
this.size = input.size();
}
public DataSet (T input) {
if(!(input instanceof Collection)) {
throw new IllegalArgumentException("Input needs to be Collection"); //either this or a ClassCastException later
}
this.data = input;
this.size = ((Collection<?>) input).size();
}
public T getData() {
return data;
}
public long getSize() {
return size;
}
}
Both work if used correctly, but allow for mistakes as well, since I'm not sufficiently able to describe to the compiler what I want allowed there ('T is the same as I' or 'T needs to extend Collection in this Constructor only').
So; How do I define a constructor that can put constraints on its Class' type parameter(s) without introducing new type parameters for itself or the class and with compiler support for usage?