Java 一般使用错误

Java generic usage error

下面的代码使用简单的泛型并正确编译。当我尝试创建 McDelayQueue 类型的对象时,出现错误。

public class McDelayQueue<E extends Delayed & IValue<K>, K> extends DelayQueue<E> {
    final Set keys = Collections.newSetFromMap(new ConcurrentHashMap<K, Boolean>());

    @Override
    public E take() throws InterruptedException {

        E data = super.take();
        final K key = data.getKey();
        keys.remove(key);
        return data;
    }

    @Override
    public void put(E e) {
        if (!keys.contains(e.getKey())) {
            keys.add(e);
            super.put(e);
        }
    }
}

这是一个 E class :

public class DelayQueryKey<T> implements Delayed, IValue {
    private T key;
    private long startTime;

    public DelayQueryKey(T key, long delay) {
        this.key = key;
        this.startTime = System.currentTimeMillis() + delay;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = startTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MINUTES);
    }

    @Override
    public int compareTo(Delayed o) {
        if (this.startTime < ((DelayQueryKey) o).startTime) {
            return -1;
        }
        if (this.startTime > ((DelayQueryKey) o).startTime) {
            return 1;
        }
        return 0;
    }

    @Override
    public String toString() {
        return "{" +
            "key='" + key + '\'' +
            ", startTime=" + startTime +
            '}';
    }

    public T getKey() {
        return key;
    }
}

但是当我尝试创建实例时:

  McDelayQueue<DelayQueryKey<String>, String> delayQueryKeys = new McDelayQueue();

我得到这个编译时错误:

Error:(14, 69) java: type argument pubsub.delayqueue.custom.DelayQueryKey<java.lang.String> is not within bounds of type-variable E !!

这是怎么回事?

您在 DelayQueryKey class 定义中使用原始 IValue 类型

class DelayQueryKey<T> implements Delayed, IValue {

DelayQueryKey<String> 因此不符合

设定的界限
McDelayQueue<E extends Delayed & IValue<K>, K>

相反,对其进行参数化(适当地)

class DelayQueryKey<T> implements Delayed, IValue<T> {

虽然在这种情况下没有必要,但养成向需要它们的构造函数调用提供类型参数(菱形运算符或其他方式)的习惯

new McDelayQueue<>();