双方施法有什么区别:
List <String>myNumbers = new ArrayList<String>();
与
List <String>myNumbers = new ArrayList();
和
List myNumbers = new ArrayList<String>();
答案 0 :(得分:1)
第一个示例是类型安全的意思,如果您尝试将除String
对象之外的任何内容添加到myNumbers
列表中,那么您将收到编译器错误。
List <String> myNumbers = new ArrayList<String>();
第二个示例也是类型安全的,编译器将确保只有String
类型的对象存储在myNumbers
列表中。
List <String> myNumbers = new ArrayList();
原始类型是通用类或没有任何接口的接口的名称 类型参数。
在JDK 1.5中引入泛型时,仅保留原始类型以便与旧版本的java向后兼容。尽管仍然允许使用原始类型,但您应该避免使用它们,原因如下:
最后一个示例是原始类型,这意味着我们可以将所有类型的对象添加到myNumbers
列表中。但是,您应该尽可能避免使用它们。
List myNumbers = new ArrayList<String>();
注意 - 如果您未指定类型,如上所示,myNumbers
列表中的每个项目都会被视为Object
类型。
从您已经展示的示例来看,这是首选方式:
List <String> myNumbers = new ArrayList<String>();
但是,只要编译器可以从中推断类型参数,就可以用一组空类型参数(<
>
)替换调用泛型类构造函数所需的类型参数。背景。
意思是代替:
List <String> myNumbers = new ArrayList<String>();
我们可以这样做:
List <String> myNumbers = new ArrayList<>();
答案 1 :(得分:0)
让我们仔细阅读每一个
List <String>myNumbers = new ArrayList<String>();
这表明myNumbers
列表只会存储Strings
。这是因为new ArrayList<String>()
也仅限制为'String`对象。
转到第二个例子......
List <String>myNumbers = new ArrayList();
与以前相同,myNumbers
仅限于存储String
个对象。不同的是new ArrayList()
将存储任何对象,它是原始类型。所以这个编译。 new ArrayList()
将保留String
个对象,因此会进行编译。关于约束和类型减少的更多内容可以在18.2.2 of the Java Language Specifications部分中阅读。这属于推理的主题。
第18章类型推断
各种编译时分析需要推理尚未知道的类型。其中主要是通用方法适用性测试(第18.5.1节)和通用方法调用类型推断(第18.5.2节)。一般来说,我们将关于未知类型的推理过程称为类型推断。
在较高级别,类型推断可以分解为三个过程:
- Reduction对表达式或类型进行兼容性断言,称为约束公式,并将其减少为推理变量的一组边界。通常,约束公式会减少到其他约束公式,这些公式必须递归地减少。遵循一个过程来识别这些附加约束公式,并最终通过约束集表达推断类型的选择将每个约束公式呈现为真的条件。
最后你的第三个例子......
List myNumbers = new ArrayList<String>();
这是最有趣的一个,因为它引入了类型擦除和原始类型。基本上发生的事情是,即使使用参数化的new ArrayList<String>()
实例化String
,Java也允许忽略它以允许原始类型,并且擦除的概念和规则是如何实现的。至少这是人们可以从Java语言规范的第4.8和4.6节中推断出来的。
4.8。原始类型
为了便于与非泛型遗留代码接口,可以使用参数化类型(第4.5节)的擦除(第4.6节)或者元素类型为的数组类型(第10.1节)的擦除作为类型。参数化类型。这种类型称为原始类型。
...此外
4.6。键入Erasure
...跳过几个要点
类型擦除还将构造函数或方法的签名(第8.4.2节)映射到
没有参数化类型或类型变量的签名。构造函数或方法签名s的擦除是由与s相同的名称和s中给出的所有形式参数类型的擦除组成的签名。如果方法或构造函数的签名被删除,方法的返回类型(第8.4.5节)和泛型方法或构造函数的类型参数(第8.4.4节,第8.8.4节)也会被擦除。
删除泛型方法的签名没有类型参数。