我正在尝试创建一个函数来处理(可比较的)元素的排序列表。因此,我使用通用的 <T extends List<? extends Comparable>> ,只要我不需要任何需要 <? extends Comparable> 作为输入的特定于列表的操作,它就可以工作。但是在下面的代码片段中(最简单的例子:计算两个排序列表的交集) C.add((Comparable)(A.get(posA))); 行被编译器拒绝,声称 add 需要参数 ? extends Comparable ,而 Comparable 显然不是。

public static <T extends List<? extends Comparable>> T intersect (T A, T B) {
    T C = (T) A.getClass().newInstance();
    int posA = 0;
    int posB = 0;
    while(posA<A.size()&&posB<B.size()) {
        if (A.get(posA).compareTo(B.get(posB))>0) posB++;
        else if (A.get(posA).compareTo(B.get(posB))<0) posA++;
        else if (A.get(posA).equals(B.get(posB))) {
            C.add((Comparable)(A.get(posA)));
            posA++; posB++;
        }
    }
    return C;
}

我应该如何告诉编译器 A.get(posA) 是有效类型 ? extends Comparable ?显然转换不起作用,我希望例程接受并返回任意可比较项(整数、字符串、自定义对象等)的列表

最佳答案

您没有注意到代码中的所有不安全类型语句,其中有多个不安全类型转换吗?
你真的有很多。这通常意味着整体方法不是正确的方法。

事实上,如果你了解了 Java 中泛型的工作原理,事情就没有那么复杂了。
这可以帮助你:

  • https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html
  • https://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html

  • 以下是您应该根据实际代码考虑的主要事项:
    1) 不要使用原始类型,例如 List<? extends Comparable>>Comparable 是一个泛型类。
    2) 除了 null 之外,您不能在声明 List<? extends Foo> 的列表中添加任何内容,即使用上限通配符。最后一个允许使 List 协变:接受 Foo 和任何子类,但具有先前的限制。所以你不想使用它。
    3) 您可以实例化一个泛型 ArrayList ,而无需为 T 声明泛型方法类型 ArrayList 。将 T 用于 Comparable 类型会使事情变得非常简单。
    4)你想尽可能地避免反射。

    通过遵循这些想法,您可以编写如下所示的代码:
    public static <T extends Comparable<T>> List<T> intersect (List<T> A, List<T> B) {
        List<T> list = new ArrayList<>();
        int posA = 0;
        int posB = 0;
        while(posA<A.size()&&posB<B.size()) {
            if (A.get(posA).compareTo(B.get(posB))>0) posB++;
            else if (A.get(posA).compareTo(B.get(posB))<0) posA++;
            else if (A.get(posA).equals(B.get(posB))) {
                list.add(A.get(posA));
                posA++; posB++;
            }
        }
        return list;
    }
    



    如果为参数声明 List,则在编译时将不知道 List 的类型。因此,您将不可避免地以不安全的强制转换结束。
    例如 :
    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>, L extends List<T>> L intersect(L A, L B)  {
    
        if (A.getClass() != B.getClass()) {
            throw new IllegalArgumentException("not same type between ...");
        }
        List<T> list = A.getClass()
                        .newInstance(); // uncheck
    
        int posA = 0;
        int posB = 0;
        while (posA < A.size() && posB < B.size()) {
            if (A.get(posA)
                 .compareTo(B.get(posB)) > 0)
                posB++;
            else if (A.get(posA)
                      .compareTo(B.get(posB)) < 0)
                posA++;
            else if (A.get(posA)
                      .equals(B.get(posB))) {
                list.add(A.get(posA));
                posA++;
                posB++;
            }
        }
        return (L) list; // uncheck
    }
    

    关于java - 在泛型声明中使用 "? extends"时,可以避免 Java 中的参数不匹配吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52454297/

    10-14 16:46