警告:为varargs参数创建Object&amp; Serializable&amp; Comparable <! - ? - >的通用数组

时间:2010-11-26 04:25:02

标签: java generics programming-languages

如果我用不同类的对象调用(泛型)varargs方法,我会收到一个有趣的警告:

List<?> result =  Arrays.asList("1", 1);
  

为varargs参数创建了Object&amp; Serializable&amp; Comparable的通用数组

我可以通过强制转换到公共接口或类来消除警告,

List<Serializable> result = asList((Serializable) "1", (Serializable) 1);

Object&Serializable&Comparable<?>是什么意思?是否可以在方法签名的泛型类型注释中使用(例如extendssuper)?

3 个答案:

答案 0 :(得分:3)

Object以及接口ComparableSerializable是类IntegerString共有的超类型。

由于泛型中的类型擦除和数组的协方差,泛型和数组不能很好地相互混合。方法Arrays#asList采用varargs作为输入,而在Java中,varargs在内部使用数组实现。因此警告。 (您可以在Josh Bloch的Effective Java中详细了解这一点。)

现在回到第二个问题,可以在方法签名中使用<Object & Comparable<Whatever> & Serializable>来指定类型参数的约束。 (参见this answer。)但是,Java不允许在泛型类型注释中使用此类型。

换句话说,以下内容有效:

public static void <A extends Comparable<A> & Serializable> meth(A a);

但以下不是:

List<Serializable & SomeOtherInterface> list = ...;

答案 1 :(得分:1)

我认为因为所有对象类型都是Serializable和Comparable(String and Integer),然后编译器说数组中的所有元素都将具有Object类型并实现Serializable和Comparable接口。

我怀疑Serializable&amp; Comparable可以在java代码中正常使用,你总是可以正常实现它们并收到相同的警告: - )

public class ComparableAndSerializableClass implements Comparable<ComparableAndSerializableClass>, Serializable{

    public static void main(String[] args) {
        List<?> result = Arrays.asList( "1", 1, new ComparableAndSerializableClass());
        for (Object comp : result) {
            System.out.println(comp.getClass());
        }
    }

    @Override
    public int compareTo(ComparableAndSerializableClass o) {
        return 0;
    }
}

答案 2 :(得分:0)

如果你有Foo<...>这样的通用类型,那么你可以使用辅助方法为你调用Arrays.asList()

public static List<Foo<?>> asList( Foo<?> ... foos ) {
    return Arrays.asList( foos );
}

Java编译器将为varargs参数创建一个通用数组,然后您可以在调用Arrays.asList()时安全地使用该数组。如果您希望所有Foo具有相同的内部类型:

public static <T> List<Foo<T>> asList( Foo<T> ... foos ) {
    return Arrays.asList( foos );
}