List和List<之间有什么区别?>, List<T>, List<E>, List<Object>?

1. 列表

List:是一个原始类型,因此不是类型安全的。它只会在强制转换错误时生成运行时错误。当强制转换错误时,我们希望出现编译时错误。不建议使用。

2. 列表< ?>

列表< ?>是一个无界通配符。但我不确定这是干什么用的?我可以打印一个List<?>无问题:

public static void test(List<?> list){
    System.out.println(list);   // Works
}

为什么我不能向List<?>?

public static void test(List<?> list){
    list.add(new Long(2));     // Error
    list.add("2");             // Error
    System.out.println(list);
}

3. 目前居住;rolelabel T >

public static void test(List<T> list){   // T cannot be resolved
    System.out.println(list);
}

我不明白这个语法。我看到了类似这样的东西,它起作用了:

public <T> T[] toArray(T[] a){
    return a;   
}

有时,我看到<T>,或<E>,或<U>, <T,E>。它们都是一样的还是代表着不同的东西?

4. List <物体>

这给出了错误“the method test(List<Object>) is not applied for the argument List<String>”:

public static void test(List<Object> list){
    System.out.println(list);
}

如果我尝试这样做,那么我得到“不能从列表<字符串>到列表<对象>”:

test((List<Object>) names);

我很困惑。字符串是对象的子类,所以为什么List<String>不是List<Object>的子类?


当前回答

在你的第三点,“T”不能解析,因为它没有声明,通常当你声明一个泛型类时,你可以使用“T”作为绑定类型参数的名称,许多在线示例包括oracle的教程使用“T”作为类型参数的名称,例如,你声明一个类:

public class FooHandler<T>
{
   public void operateOnFoo(T foo) { /*some foo handling code here*/}

}

你是说,FooHandler的operateOnFoo方法期望一个类型为“T”的变量在类声明本身声明,考虑到这一点,你可以稍后添加另一个方法,如

public void operateOnFoos(List<T> foos)

在所有情况下,T, E或U都是类型参数的标识符,你甚至可以有多个使用该语法的类型参数

public class MyClass<Atype,AnotherType> {}

在你的第四点,虽然实际上Sting是对象的子类型,在泛型类中没有这样的关系,List<String>不是List<Object>的子类型,从编译器的角度来看,它们是两种不同的类型,这是最好的解释在这个博客条目

其他回答

让我们在Java历史的背景下讨论它们;

列表:

List意味着它可以包含任何对象。List是在Java 5.0之前发布的;为了向后兼容,Java 5.0引入了List。

List list=new  ArrayList();
list.add(anyObject);

列表< ?>:

? 指未知对象,而不是任何对象;通配符?引入是为了解决泛型类型构建的问题;看到通配符; 但这也导致了另一个问题:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error

List< T> List< E>

表示在项目库中没有T或E类型的前提下的泛型声明。

List< Object>表示泛型参数化。

最后一部分: 虽然String是Object的子集,但是List<String>并不是继承自List<Object>。

我建议阅读Java谜题。它很好地解释了声明中的继承、泛型、抽象和通配符。 http://www.javapuzzlers.com/

不能将List<String>强制转换为List<Object>的原因是,它将允许您违反List<String>的约束。

考虑以下场景:如果我有一个List<String>,它应该只包含String类型的对象。(这是最后一节课)

如果我可以将其转换为List<Object>,那么这就允许我将Object添加到该列表中,从而违反了List<String>的原始契约。

因此,一般来说,如果类C继承自类P,你不能说GenericType<C>也继承自GenericType<P>。

注意:我在之前的回答中已经评论过这一点,但我想在此展开。

问题2没问题,因为“System.out.println(set);”意味着“System.out.println(set. tostring());”set是List的一个实例,因此编译器将调用List. tostring ();

public static void test(List<?> set){
set.add(new Long(2)); //--> Error  
set.add("2");    //--> Error
System.out.println(set);
} 
Element ? will not promise Long and String, so complier will  not accept Long and String Object

public static void test(List<String> set){
set.add(new Long(2)); //--> Error
set.add("2");    //--> Work
System.out.println(set);
}
Element String promise it a String, so complier will accept String Object

问题3:这些符号是一样的,但是你可以给它们不同的规格。例如:

public <T extends Integer,E extends String> void p(T t, E e) {}

问题4:集合不允许类型参数协方差。但是数组允许协方差。