为什么在Java泛型中,集合的右侧类型并没有任何影响?
使用Java的泛型特性,我创建了一个列表对象,在左侧我使用原始类型列表,在右侧我使用泛型类型ArrayList为什么在Java泛型中,集合的右侧类型并没有任何影响?,java,generics,collections,java-6,Java,Generics,Collections,Java 6,使用Java的泛型特性,我创建了一个列表对象,在左侧我使用原始类型列表,在右侧我使用泛型类型ArrayList List myList=new ArrayList<String>(); 我希望我会得到一些编译错误,但是这个程序运行得很好。但是如果我在左侧使用泛型类型List,在右侧使用原始类型ArrayList,并尝试在列表中添加一个int值,我会得到预期的编译错误 List<String> myList=new ArrayList(); myList.add(101)
List myList=new ArrayList<String>();
我希望我会得到一些编译错误,但是这个程序运行得很好。但是如果我在左侧使用泛型类型ListList<String> myList=new ArrayList();
myList.add(101);//The method add(int, String) in the type List<String> is not applicable for the arguments (int)
List myList=new ArrayList();
myList.add(101)//类型列表中的add(int,String)方法不适用于参数(int)
为什么在Java泛型中,集合的右侧类型并没有任何影响?为什么Java允许我们在没有任何效果的情况下这样做呢?我使用的是Java1.6。请解释。如果您没有在左侧提供泛型类型参数,
列表将声明为原始类型。这意味着编译器不知道在该列表中存储什么是合法的或不合法的,并且依赖程序员执行适当的instanceof
检查和强制转换
原始类型还具有删除类中出现的所有泛型类型信息的效果
JLS提供了一个警告,您应该会在IDE或编译器中看到有关分配给原始类型的警告:
确保始终存在可能违反键入规则的情况
标记后,对原始类型成员的某些访问将导致
编译时未检查的警告。未选中编译时规则
访问原始类型的成员或构造函数时的警告如下
如下:
在字段赋值时:如果左侧操作数的类型为
原始类型,则在删除时会出现编译时未检查警告
更改字段的类型
在调用方法或构造函数时:如果类的类型
或搜索接口(§15.12.1)是原始类型,然后是编译时
如果擦除更改了任何形式的
方法或构造函数的参数类型
当
形式参数类型在擦除时不会改变(即使结果
类型和/或抛出子句更改),用于从字段读取,或用于
类创建原始类型的实例
Tom G的回答很好,解释得很详细,但我觉得你至少已经知道了一些东西,因为你说过:
我希望我会得到一些编译错误
所以,让我来具体说明这一部分
您没有收到任何编译错误的原因是,泛型是在java中作为事后考虑添加的,因此,许多与泛型相关的问题(应该是错误)已降级为警告,以避免破坏现有代码
最可能发生的是,这些警告在您的开发环境中被关闭
纠正问题的步骤:
转到IDE的选项
查找“警告”部分
启用所有功能
当你看到这个庞大的数字后,从地板上抬起你的下巴
你会收到很多警告
禁用所有没有任何意义的警告,如“硬编码字符串”或“成员访问不符合<代码>此代码>”等,保留所有其他内容。请确保您保留的内容中包含“参数化类的原始使用”之类的内容
“…泛型集合类型的右侧并没有任何效果”基本上是正确的。当“var”关键字替换为“List”时,右侧的generic确实会起作用。下面的代码创建字符串的ArrayList
var myList = new ArrayList<String>();
var myList=new ArrayList();
乍一看,myList似乎只能存储字符串
也许是一瞥吧。但认识到“只能存储字符串的列表”是不存在的,至少在标准API中是不存在的,这一点非常重要
只有列表
,如果您试图向其中添加非字符串
的内容,即将其声明为列表
,则必须向编译器提供正确的指令,以严厉批评您
如果您将其声明为“纯旧列表
”,编译器没有关于允许或不允许您将什么放入其中的指令,因此您可以存储支持数组的类型边界内的任何内容,即任何对象
您在赋值的RHS上说new ArrayList()
,这一事实与此无关:Java不会尝试跟踪分配给变量的值。变量的类型就是您声明的类型。请阅读可能重复的内容,谢谢您的回复,但我主要关心的是我正在声明List myList=new ArrayList();乍一看,myList似乎只能存储字符串,因为我在右侧提到了类型字符串。但是myList可以存储任何类型的对象。为什么Java允许我们在右边提到类型?这不令人困惑吗?也许,这就是他们在Java7中引入菱形操作符的原因。我的帖子缺少了泛型。它应该是:var myList=new ArrayList();
var myList = new ArrayList<String>();