3

它编译并运行成功!

List a=new ArrayList<String>();
a.add(new Integer(5));

有人可以解释一下吗?

4

6 回答 6

6

原因是您将变量声明a为原始列表,即List没有任何关联类型:

List a = new ArrayList<String>();

就此而言,即使这将编译并运行:

List a = new ArrayList<Date>();
a.add(new Integer(5));

generics还有一个关于和type erasure这里的注释:

Java 编译器将泛型实现为称为擦除的前端转换。类型擦除适用于泛型的使用。当使用泛型时,它们被转换为编译时检查和运行时类型转换。

由于类型擦除机制,此代码:

List<String> a = new ArrayList<String>();
a.add("foo");
String x = a.get(0);

被编译成:

List a = new ArrayList();
a.add("foo");
String x = (String) a.get(0);

同样你的代码:

List a = new ArrayList<String>();
a.add(new Integer(5));

被编译成这个(由于类型擦除):

List a = new ArrayList();
a.add(new Integer(5));

因此不会产生编译或运行时错误。

但是,当您尝试从列表中获取项目时,您会注意到不同之处:

int i = a.get(0); // compilation error due to type mismatch

这是因为您的列表被声明为原始类型。为避免此错误,您需要使用泛型来声明您的列表,或者像上面那样进行类型转换。IE

在列表中使用泛型类型:

List<Integer> a = new ArrayList<Integer>();
a.add(new Integer(5));    
int i = a.get(0);

或者做这个铸造:(不推荐

List a=new ArrayList<Date>();
a.add(new Integer(5));
int i = (Integer) a.get(0);

PS:请注意,在运行时无法找出特定类型,例如 String 用于声明您的列表对象。

于 2013-07-30T09:43:58.823 回答
1

You should do

List<String> a = new ArrayList<String>();
a.add(new Integer(5));
  • List means that compiler will check whether only String objects are being added into the collection.

Can anybody explain this?

This is possible because

  • There is no type safety at runtime because of type erasuse
  • The statement List a means there is no compile time check what objects are being added into the list.

As of java 7 you do not have to write List<String> a = new ArrayList<String>() for type safety. You can simply use the diamond operator and achieve the same using List<String> a = new ArrayList();

于 2013-07-30T09:41:37.673 回答
1

这是因为旧的遗留代码被允许将任何东西(除了原语)放入一个集合中。为了支持遗留代码,Java 5 和 Java 6 允许您的新类型安全代码使用旧代码。

因此,Java 5 或 Java 6 编译器被迫让您编译新的类型安全代码,即使您的代码调用了旧类的方法,该方法采用非类型安全参数并且谁知道用它做什么。

事实上编译器会警告你。编译器从编译中生成了一个完全有效的类文件,但它很友好地告诉你,用很多话告诉你,“我真的希望你知道你在做什么,因为这段旧代码不尊重(甚至不知道)您的<String>打字,并且可以为您的宝贝做任何想做的事ArrayList<String>。”

于 2013-07-30T09:56:46.977 回答
1

您没有在实际定义中指定泛型类型

如果你写

List<String> a = new ArrayList<String>();
a.add(new Integer(5));

不会编译。

于 2013-07-30T09:39:39.437 回答
1

List a是一个没有泛型的原始类型。这与您能够向其中添加整数的原因完全相同。

要强制执行正确的行为,请将 List 更改为使用泛型。

List<String> a
于 2013-07-30T09:43:40.903 回答
1

通用数据在编译后被删除。这意味着

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

将在类文件中更改为您在下面看到的内容

List a=new ArrayList();

现在回答你的问题,类型aList,它是原始列表,你可以添加任何东西。存在泛型以限制编译时间。这意味着说你有

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

此行将生成编译时错误

a.add(new Integer(1)); //error
于 2013-07-30T09:44:55.873 回答