泛型声明在Java中的差异

时间:2012-04-10 17:33:43

标签: java generics

 List<String> v = new ArrayList<String>();

我理解泛型可以帮助您声明ArrayList()具有String类型的对象。我的问题是 以下是如何与上述不同的?

 List<String> v = new ArrayList();

或以下与其他人不同的

List v = new ArrayList<String>();

5 个答案:

答案 0 :(得分:4)

List<String> v = new ArrayList();

这个并不是真正的功能差异。右侧的类型参数实际上没有做任何事情。它被用作样式的问题并且避免使用Raw类型,这被认为是编程错误。实际上,在Java 7中它已被增强,所以你可以这样做:List<String> v = new ArrayList<>();而不必在右侧重复自己。

List v = new ArrayList<String>();

没有类型参数的列表称为原始类型。在使用泛型的新代码中声明原始类型通常被认为是编程错误。基本上,当您以这种方式声明时,根本没有进行类型检查,您可以在该列表中放置任何内容。

Java泛型是一个编译时间检查。因此,编译时引用的类型很重要。如果您的引用是Raw List类型,那么您在右侧声明的内容并不重要,这就是编译器将检查的内容。

List<String>实际上不是“包含字符串的列表”。这是一个“列表,我已经要求编译器返回错误和/或警告我,如果我在那里放一些不是字符串的东西。如果你忽略编译器警告,很有可能在那里得到的东西不是'一个字符串。

答案 1 :(得分:1)

public static void main(String[] args) throws Exception {
    List<String> list1 = new ArrayList<String>();
    List<String> list2 = new ArrayList(); //This is equivalent to list1 but with compilation warning
    List list3 = new ArrayList<Integer>(); //This is equivalent to list3 = new ArrayList<Object>()
    //list1.add(new Object()); //does not compile
    //list2.add(new Object()); //does not compile
    list3.add(new Object()); //this is fine
    list1 = list3; //ok, but
    System.out.println(list3.get(0)); // this is fine
    System.out.println(list1.get(0)); //Runtime error: ClassCastException
    //List<Object> list5 = list1; //does not compile        
    List<Object> list5 = list3; //ok
}

答案 2 :(得分:1)

List v = new ArrayList();

这是在java 5声明列表之前的方式。

List<String> v = new ArrayList<String>();

它使用了java中引入的泛型。它增加了编译时类型的安全性。

List<String> v = new ArrayList<>(); 

只是java 7中引入的一个优化。它只是简化了代码 通过保持类型安全

答案 3 :(得分:0)

在第一个和第三个案例(new ArrayList<String>())中,您实例化了一个可以容纳ArrayList个实例的String

在第二种情况下(new ArrayList()),您实例化ArrayList可以容纳Object个实例(即任何类型的实例 - 甚至混合和匹配)

在第一个和第二个案例(ArrayList<String> v)中,您声明了一个可以容纳ArrayList个实例的String个实例

在第三种情况下(ArrayList v),您声明了一个ArrayList的实例,该实例可以包含Object的实例。

第二种情况的问题是,如果你要获得一个“原始”ArrayList(就像那个实例化的那样),那么它理论上可以容纳任何东西;不只是String个实例,这是声明用户所期望的。

同样,在第三种情况下,您创建了一个ArrayList,它应该保留String,但声明的用户不知道并且可能尝试将其他对象实例放入其中

注意:当然,在JVM中,泛型类型信息会丢失,因此执行方面没有区别,但是对于编程类型安全性,编译器会标记错误的使用。这样,就不需要动态检查/确保放入/放出列表的对象的类型 - 你可以假设它们是正确的类型,因为编译器确保了这个

答案 4 :(得分:0)

这些全部编译,都是有效的。第二种情况可能只会发出警告 - 由于List<String>,您将无法添加任何非字符串的内容。在第三种情况下,你有相反的问题。您可以添加不是字符串的内容,但结果可能会遇到运行时异常。