我只是意识到编译器允许以多种方式定义地图。这些声明之间是否有区别,哪种是“正确”的方式:
Map<String, String> data = new HashMap<String, String>();
Map<String, String> data = new HashMap<>();
Map<String, String> data = new HashMap();
答案 0 :(得分:0)
Map<K, V> m = new HashMap();
这是初始化m
的最糟糕方式。 HashMap
这里是原始类型,这意味着它忽略所有通用数据。它安全地转换为Map<K, V>
,但原始类型的使用会导致编译器警告。这是有充分理由的,因为由于忽略了通用数据,您可以这样做:
Map<String, String> m;
Map<Int, Int> m2 = new HashMap(m); // no error
原始类型存在与旧的Java 5之前的代码的互操作性,其中泛型不存在。所有泛型类型都被视为它们的擦除。因此,原始HashMap
构造函数不再需要Map<? extends K, ? extends V>
,它需要原始Map
。 get
方法不再需要K
返回V
,需要Object
(删除K
)并返回Object
(擦除V
)。这极大地损害了类型安全性,并且将原始类型静默转换为参数化类型没有帮助。
绝对不要这样做。
Map<K, V> m = new HashMap<K, V>();
这是初始化泛型类型的Java-Java之前的方法。由于HashMap
构造函数正在传递类型参数,因此它比第三种方式更安全。通用信息现在用于完整扩展,一切都是类型安全的。它比第三种方式更好,但如果可以,你也可以采用第二种方式。
Map<K, V> m = new HashMap<>();
这是初始化Java 7中引入的泛型类型的新方法。这与第一种方法相同,只是因为在a的左侧和右侧写出相同类型的参数很痛苦。声明,右侧可省略类型参数。 <>
被称为钻石运算符。尽可能使用它。
第二种方式,如果你使用Java 7+,第一种方法,如果你不是,第三种方式太邪恶甚至不考虑使用。
答案 1 :(得分:0)
Map<String, String> data = new HashMap<String, String>();
,其中泛型被添加到Java语言中,它被称为原始类型。Map<String, String> data = new HashMap<>();
,其中引入了菱形运算符<>
以使声明更简洁,因为HashMap<>
的类型参数可以从{{1}推断出来}}。它是第一种符号的简称(甜的语法糖)。Map<String, String>
,因为没有泛型,所以你没有指定类型参数,键和值只是Map data = new HashMap();
。要回答您的问题,请始终使用选项一或两,因为您获得了更强的类型安全性。选项三只是一种过时而危险的方式,可能会导致错误,因为您可以声明如下内容:
Object
这仅适用于Java 类型擦除。在运行时时,HashMap mixedMap = new HashMap();
mixedMap.put("bla", 20);
// Add further elements...
HashMap<String, String> map = new HashMap(mixedMap);
和mixedMap
都被视为map
,因此强制转换不再安全且上述结构有效。但是,如果您使用类型参数(如选项一或二),您将获得编译器抛出的类型安全警告和错误。
那么,为什么第三种选择仍然可能,如果它有负面影响?答案是Java设计者决定保持向后兼容性,因此他们必须使用类型擦除,遗憾的是它允许关于类型安全的关键代码。