2014-09-05 108 views
4

最近我看了一段看起来很奇怪的代码。正如我们所知道的,当我们需要使用它们时,我们需要在集合中初始化泛型类型。另外,我们知道集合可以包含集合作为其元素。ArrayList Generic without Type

代码:

public class Solution { 
public static void main(String args[]) { 
    ArrayList res = returnlist(); 
    System.out.print(res.get(0)); 
} 
public static ArrayList<ArrayList<Integer>> returnlist() { 
    ArrayList result = new ArrayList(); 
    ArrayList<Integer> content = new ArrayList<Integer>(); 
    content.add(1); 
    result.add(content); 
    return result; 
}} 

我的问题是

  • 我们为什么可以使用ArrayList result = new ArrayList();创建一个对象,因为我们还没有给集合的实际类型的元素。
  • 我们为什么可以使用result.add(content);到集合添加到集合与集合“结果”只是一个普通的集合。我们没有把它定义为一个ArrayListArrayList

回答

7

爪哇通用集合不存储与一种类型以确保向后预J2SE 5.0兼容性。类型信息在添加到通用集合时被删除。这被称为Type Erasure

这意味着,一个通用的集合可以被分配到一个非通用的参考。

所有Java泛型确实是确保你不能错误的类型添加到一个通用的列表,并从做一个explicit投上检索您节省;即使它仍然完成implicitly

进一步就此

+1

+1我认为这是最有意义的答案 – ne1410s 2014-09-05 16:03:27

+1

+1认可。@ ne1410s – Kai 2014-09-05 16:05:32

+0

2 +1但只有1分...已经StackOverflow失去了计数能力? :P – 2014-09-05 16:07:29

0

它可能是从仿制药来了到Java之前的残余(Java的4或5,我认为)。

+0

不一定是残余,但肯定是不使用泛型的功能。您必须在结果上投射这些项目才能在获得它们时使用它们。 – 2014-09-05 15:55:54

+0

是的。似乎我们需要照顾我们存储在没有泛型的ArrayList中的事物。 – Kai 2014-09-05 16:00:17

0

泛型添加到Java只在Java 5在此之前,当你使用一个集合,它总是意味着对象的集合。旧的语法保留为了向后兼容。所以ArrayList result = new ArrayList()实际上是创建一个ArrayList<Object>。由于ArrayList也是一个对象,因此可以将content添加到变量result

+0

有道理。但在日常编程中,它仍然是一种非常流行的方式来使用不带泛型的集合? – Kai 2014-09-05 15:59:27

+0

不建议用于新的代码。但是在Java 5之前编写了很多代码,并且在维护代码甚至扩展它时,人们倾向于使用旧的风格。 – 2014-09-05 16:03:22

+0

非常感谢。 – Kai 2014-09-05 16:07:28

0

为什么我们可以用ArrayList result = new ArrayList();来创建一个对象,因为我们没有给这个集合实际的元素类型。

因为基于java希望它向后兼容。泛型更多的是确保类型安全的编译器特性,集合可以在运行时存储任何类型的对象。

Java编译器不会给你编译器错误此,但它一定是给你编译器警告,这是不安全的使用泛型类没有类型。

2

只要加上p rovide总结答案

老办法:

(A) ArrayList result = new ArrayList(); 

将创建一个ArrayList举办 “对象”


新途径:

ArrayList<Integer> content = new ArrayList<Integer>(); 

这代表一个ArrayList将举行“整数”对象。这是为编译时类型检查目的而引入的。


为什么?

考虑第一种情况。它的输入类型是Object。我们知道Object是所有类的超类。我们可以传入一个Integer对象,String对象等等。获取数据时,开发人员必须执行正确的类型转换。如果说开发商一开始认为的代码将接受Integer对象,所以他增加了以下类型转换而获取

Integer integer=(Integer) content.get(0); 

这应该是工作数据。但是如果错误地传递了一个字符串,将会导致运行时错误。

如何避免?

通过引入编译时检查


它是如何工作的?

当我们只指定参数化类型时可以将Integer对象添加到ArrayList集合中。否则会显示错误。

content.add(3); // will work 
content.add("HARSHAD"); // error shown 

如果参数泛型类型是类型检查的目的数据如何正确可以从列表中检索到的?

编译器隐式执行类型转换。请参阅示例代码

List<Integer> list=new ArrayList<Integer>(); 
list.add(1); 
list.add(2); 
Integer integer=list.get(0); 
System.out.println(integer); 

执行编译时编译器实际执行的操作是什么?

//perform type erasure 
(B) List list=new ArrayList(); 
    list.add(1); 
    list.add(2); 

// the arraylist inturn accepts Object when you run the code 

//add casting 
Integer integer=(Integer)list.get(0); 

结论

如果你看到的代码(A)和(B)两者是相同的。唯一不同的是,在第二种情况下,编译器隐式执行相同的操作。

最后回答你的问题......

ArrayList result = new ArrayList(); 

是允许向后兼容。虽然这不被推荐。

官方链接Oracle docs解释相同的概念。