创建具有附加类型约束的通用 class' 构造函数
Creating generic class' constructor with additional type constraints
我想创建用于算法测试的数据集。
我有一个通用包装器 class,它包含 T 类型的数据以及有关数据集的任意 size/complicatedness 的信息,以便能够将输入大小映射到运行时。
因为不是我想要测试的所有东西都只是某物的倍数,所以我不想限制 T.
但是,我想要一个 'recognizes' 作为 Collection 的构造函数,然后可以自己推断大小。
下面的代码确实有效,但是有一个编译器警告是有原因的
或者需要分别抛出Exception。
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;
}
}
如果使用正确,两者都可以工作,但也允许出现错误,因为我没有足够的能力向编译器描述我想要在那里允许的内容('T is the same as I' 或 'T needs to extend Collection in this Constructor only')。
所以;我如何定义一个可以对其 Class' 类型参数施加约束的构造函数,而无需为其自身或 class 引入新的类型参数,并且编译器支持使用?
我认为最好的方法是将您的实现拆分为 2 child,例如:
public interface DataSet<T>{
T getData();
long getSize();
}
class SimpleDataSet<T> implements DataSet<T>{
private final long size;
private final T data;
public SimpleDataSet(T data, long size) {
this.data = data;
this.size = size;
}
public T getData() {
return data;
}
public long getSize() {
return size;
}
}
class CollectionDataSet<I> implements DataSet<Collection<I>>{
private final Collection<I> data;
public CollectionDataSet(Collection<I> data) {
this.data = data;
}
public Collection<I> getData() {
return data;
}
public long getSize() {
return data.size();
}
}
但如果做不到,您可以尝试以下操作:
public <I> DataSet (Collection<I> input) {
this.data = (T) input;
this.size = input.size();
}
或者
private final Collection<T> collectionData;
public DataSet (Collection<T> input) {
this.data = null;
this.collectionData = input;
this.size = collectionData.size();
}
我想创建用于算法测试的数据集。
我有一个通用包装器 class,它包含 T 类型的数据以及有关数据集的任意 size/complicatedness 的信息,以便能够将输入大小映射到运行时。
因为不是我想要测试的所有东西都只是某物的倍数,所以我不想限制 T.
但是,我想要一个 'recognizes' 作为 Collection 的构造函数,然后可以自己推断大小。
下面的代码确实有效,但是有一个编译器警告是有原因的 或者需要分别抛出Exception。
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;
}
}
如果使用正确,两者都可以工作,但也允许出现错误,因为我没有足够的能力向编译器描述我想要在那里允许的内容('T is the same as I' 或 'T needs to extend Collection in this Constructor only')。
所以;我如何定义一个可以对其 Class' 类型参数施加约束的构造函数,而无需为其自身或 class 引入新的类型参数,并且编译器支持使用?
我认为最好的方法是将您的实现拆分为 2 child,例如:
public interface DataSet<T>{
T getData();
long getSize();
}
class SimpleDataSet<T> implements DataSet<T>{
private final long size;
private final T data;
public SimpleDataSet(T data, long size) {
this.data = data;
this.size = size;
}
public T getData() {
return data;
}
public long getSize() {
return size;
}
}
class CollectionDataSet<I> implements DataSet<Collection<I>>{
private final Collection<I> data;
public CollectionDataSet(Collection<I> data) {
this.data = data;
}
public Collection<I> getData() {
return data;
}
public long getSize() {
return data.size();
}
}
但如果做不到,您可以尝试以下操作:
public <I> DataSet (Collection<I> input) {
this.data = (T) input;
this.size = input.size();
}
或者
private final Collection<T> collectionData;
public DataSet (Collection<T> input) {
this.data = null;
this.collectionData = input;
this.size = collectionData.size();
}