T扩展了Comparable <t> </t>

时间:2011-10-25 00:04:19

标签: java generics

我有以下课程。

class MyClass<T>

它使用以下构造函数。

MyClass(Comparator<T> comparator, Collection<? extends T> data)

它有一个在构造函数中设置的字段,如下所示:

this.data = Collections.unmodifiableCollection(data);

在T实现Comparable的特殊情况下,我不想要传入比较器,因为我可以使用自然顺序。所以我认为我应该可以使用这个构造函数:

public <T extends Comparable<T>> MyClass(Collection<T> data)

但显然存在类型不匹配:无法在上面的赋值语句中从Collection<T> to Collection<? extends T>转换。我尝试了各种各样的事情:添加更多通用参数,等等,但都没有工作。我似乎无法指定一个绑定说:如果你有一个实现Comparable的类型T,那就做直截了当的事。

有什么想法吗?

感谢。

3 个答案:

答案 0 :(得分:3)

不幸的是,我不认为这种“如果可比较做其他事情那样”逻辑可以用Java类型系统。

您可以将Comparable和Non-Comparable案例分成不同的类并将它们隐藏在界面后面,如下所示:

interface Interface<T> {
    public void processData();
}

class MyClass<T> implements Interface<T> {
    private final Collection<? extends T> data;
    MyClass(Comparator<T> comparator, Collection<? extends T> data) {
        this.data = data;
    }
    public void processData() {
        // ...
    }
}

class MyCompClass<T extends Comparable<T>> implements Interface<T> {
    private final Collection<? extends T> data;
    MyCompClass(Collection<? extends T> data) {
        this.data = data;
    }
    public void processData() {
        // ...
    }
}

class Factory {
    static <T extends Comparable<T>> Interface<T> create(Collection<? extends T> data) {
        return new MyCompClass<T>(data);
    }
    static <T> Interface<T> create(Comparator<T> comparator, Collection<? extends T> data) {
        return new MyClass<T>(comparator, data);
    }
}

但这可能会导致大量重复的代码。另一个选择是让MyClass在其构造函数中需要一个Comparator,并在工厂中构建该比较器:

class MyClass<T> {
    private final Collection<? extends T> data;
    MyClass(Comparator<T> comparator, Collection<? extends T> data) {
        this.data = data;
    }
    public void processData() {
        // ...
    }
}

class Factory {
    static <T extends Comparable<T>> MyClass<T> create(Collection<? extends T> data) {
        return new MyClass<T>(new Comparator<T>() {
            public int compare(T o1, T o2) {
                return o1.compareTo(o2);
            }
        }, data);
    }
    static <T> MyClass<T> create(Comparator<T> comparator, Collection<? extends T> data) {
        return new MyClass<T>(comparator, data);
    }
}

答案 1 :(得分:0)

我认为这似乎是不可能的,因为直截了当的解决方案

class MyClass<T> {

    Collection<? extends T> data;

    public MyClass(Comparator<T> comparator, Collection<? extends T> data) {
        this.data = data;
    }

    public <E extends T & Comparable<T>> MyClass(Collection<E> data) {
        this.data = data;
    }

}
编译器使用

拒绝

  

当第一个绑定是类型参数

时,无法指定任何其他绑定Comparable<T>

另见Why can't I use a type argument in a type parameter with multiple bounds?(特别是Chris Povirk的回答)。

至于解决方案,我同意Chris B。

答案 2 :(得分:0)

您可以将常规构造函数用于第一种情况,将工厂方法用于第二种情况:

class MyClass<T> {

    Collection<? extends T> data;
    Comparator<? super T> comparator;

    public MyClass(Comparator<? super T> comparator, Collection<? extends T> data) {
        this.data = data;
        this.comparator = comparator;
    }

    public static <T extends Comparable<? super T>> MyClass<T> fromComparable(Collection<T> data) {
        return new MyClass<T>(Collections.reverseOrder(Collections.reverseOrder()), data);
    }

}