我读到从Java 7开始,像在第一条语句中那样在右侧指定类型来创建Collections是不好的样式,因为编译器可以从左侧推断类型。
List<Integer> myList = new ArrayList<Integer>();
我的问题是,当像这样初始化列表时,编译器找不到类型,并且我收到未经检查的类型警告:
List<Integer> myList = new ArrayList();
编译器不会 推断 类型,因为您正在实例化 raw ArrayList
。但是它足够聪明,可以警告您在使用此(原始)对象时可能会出现问题。
值得一提的是此警告背后的原因。由于类型擦除,<Integer>
有关List
变量的参数信息()将在运行时完全消失,此时变量将保留type元素Object
。考虑以下代码段:
List rawList = new ArrayList(); //raw list
rawList.add(new String("hello"));
rawList.add(new Double(12.3d));
List<Integer> intList = rawList; // warning!
该代码段将编译,但不会生成任何警告。有一个原始列表(rawList
),您可以添加任何非原始类型到列表中,包括String
,Double
等等。但是这种分配收集到一个列表,该列表指定举行时
只有 整数,那么这是一个问题。在运行时,ClassCastException
当您尝试从中获取某些元素时会得到a
intList
,这应该是Integer
,但实际上是a String
或其他。
长话短说- 不要 将原始类型与泛型混用!
在您的情况下,如果您使用菱形,则编译器 可能 会推断出类型:
List<Integer> list = new ArrayList<>(); //¯\_(ツ)_/¯
↑↑
我发现了很多关于如何克服此限制的帖子,但没有一个关于为什么存在此限制的帖子(除了这个,它只是提到它与类型擦除有关)。 那么,为什么不能创建泛型类型的实例呢? 澄清一下,我的问题不是如何做到这一点。我知道这在C#中是可能的,那么为什么不在Java呢?我很好奇为什么Java没有实现类似的机制?为什么强迫Java开发人员使用可能导致运行时错误的笨拙变通方法?这种机制有什么潜在的危险吗?
问题内容: 在下面的示例中,为什么编译器能够为in中的第一次调用推断出通用参数,而在第二次调用中却无法推断出通用参数?我正在使用Java 6。 (编译错误为 Nonsense.Bar类型的func(Nonsense.Foo)方法不适用于参数(Nonsense.Foo) )。 注意:我了解编译器错误可以通过test()中的第三行来解决-我很好奇是否存在阻止编译器推断类型的特定限制。这 似乎 对我有足
问题内容: 将导致编译器警告。 但是,以下示例在编译时没有任何警告: 我很好奇为什么根本需要引进钻石操作员。如果不存在类型参数,为什么不对构造函数进行类型推断(因为它已经在Java中的静态方法中完成,并被Google guava等集合库所利用) 编辑 :使用millimoose答案作为起点,我了解了实际上是什么类型的擦除,而不仅仅是删除所有类型的信息。编译器实际上做了更多(从官方文档复制): 如果
我声明了一个自定义trait 的数组,以便在Rust中试验多态性,但是编译器似乎在第一个元素的子类型上进行类型推断: 编译器抱怨第一个元素是< code>Cat而不是其他元素: 向数组中添加类型也不能解决问题。因为这一次我得到了更多的错误:
我一直在尝试编写一个程序来实现任意域上的多项式,一种数学结构。我选择了Haskell作为编程语言,我使用了语言扩展。但是,我不明白为什么GHCi不能推导出的约束条件。 在我看来,保证是的实例,这意味着是的实例。所以调用就像调用一样,应该是合理的。此外,我已经编写了作为约束,并且的构造函数具有的形状,因此它还应该知道的类型是的实例。 显然,译员的想法不同。我哪里搞错了?