为什么在Java泛型的右侧类型的集合中没有任何作用?

问题描述 投票:4回答:3

使用Java的泛型功能,我创建了一个List对象,并且在左侧使用了原始类型List,在右侧使用了通用类型ArrayList

List myList=new ArrayList<String>();

并且我在列表对象中添加了一个int值。

myList.add(101);

我希望我会遇到一些编译错误,但是该程序运行良好。但是如果我在左侧使用通用类型List ,在右侧使用原始类型ArrayList并尝试添加一个int值进入列表,我得到了预期的编译错误。

List<String> myList=new ArrayList();
myList.add(101);//The method add(int, String) in the type List<String> is not applicable for the arguments (int)

为什么在Java泛型右侧集合的类型没有任何作用?以及为什么Java允许我们在没有效果的情况下这样做。我正在使用Java 1.6。请解释。

java generics collections java-6
3个回答
4
投票

如果未在左侧提供通用类型参数,则将List声明为raw类型。这意味着编译器不知道什么合法或不合法的存储在该列表中,而是依靠程序员执行适当的instanceof检查和强制转换。

原始类型还具有消除all通用类信息出现在其类中的作用。

JLS提供了much more detailed look at raw types.,您也应该在IDE或编译器中看到有关分配给原始类型的警告:

为了确保始终会潜在地违反打字规则标记后,对原始类型成员的某些访问将导致编译时未检查的警告。编译时规则未选中访问原始类型的成员或构造函数时的警告如下如下:

在分配给字段时:如果左侧操作数的类型是原始类型,如果删除,则会发生编译时未经检查的警告更改字段的类型。

在调用方法或构造函数时:如果类的类型或搜索接口(第15.12.1节)是原始类型,然后是编译时如果擦除更改了任何正式形式,则会发生未经检查的警告方法或构造函数的参数类型。

当方法调用未发生编译时未经检查的警告时,形式参数类型在擦除下不会更改(即使结果是类型和/或throws子句更改),从字段中读取或创建原始类型的类实例。


1
投票

Tom G的回答很好,并详细解释了事情,但我觉得您至少已经知道其中一些内容,因为您这样说:

我希望我会得到一些编译错误

所以,让我精确地讲这部分。

之所以没有出现任何编译错误,是因为在Java中添加了泛型,这是由于事后才想到的,因此,许多本应是错误的泛型相关问题已被降级为警告,以免破坏现有代码。

而且最有可能发生的是在开发环境中关闭了这些警告。

纠正问题的步骤:

  1. 转到IDE的选项

  2. 查找“警告”部分。

  3. 启用[[Everything

  4. 看完巨大的数字后,从地板上jaw起你的下巴收到警告。

  5. 禁用所有没有任何意义的警告,例如“硬编码字符串”或“成员访问不符合this的资格”,保留所有其他内容。确保其中包括说“粗略使用参数化类”之类的内容。


0
投票

“ ...集合的泛型右侧没有任何影响”大部分是正确的。当用“ var”关键字代替“ List”时,右侧的泛型确实起作用。下面的代码创建一个字符串数组列表。

var myList = new ArrayList<String>();
© www.soinside.com 2019 - 2024. All rights reserved.