创建具有附加类型约束的通用 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();
    }