我在程序中使用了HashMap,它运行得很好,但我不理解HashMap的这些初始化之间的区别。
假设我正在实现一个以字符为键、以整数为值的HashMap。这些有什么区别?
HashMap<Character, Integer> alphabet1 = new HashMap();
HashMap<Character, Integer> alphabet1 = new HashMap<Character, Integer>();
HashMap alphabet1 = new HashMap<Character, Integer>();
Map alphabet1 = new HashMap<Character, Integer>();
HashMap alphabet1 = new HashMap<Character, Integer>();
HashMap alphabet1 = new HashMap();
Map alphabet1 = new HashMap();
任何涉及HashMap
或Map
但没有类型参数(尖括号<和>以及它们之间的部分)的内容都是原始类型,不应使用。原始类型不是泛型的,它允许您执行不安全的操作。
"正确"的方法是
Map<Character, Integer> alphabet1 = new HashMap<Character, Integer>();
HashMap<Character, Integer> alphabet1 = new HashMap<Character, Integer>();
第一个使用接口Map作为引用类型。它通常更地道,风格也不错。
还有另一种你没有提到的方法,使用Java 7菱形操作符
Map<Character, Integer> alphabet1 = new HashMap<>();
HashMap<Character, Integer> alphabet1 = new HashMap<>();
这或多或少等同于前两种正确的方法。左侧引用类型的参数隐式提供给右侧的构造函数。
您错过了正确的选择:
Map<Character, Integer> alphabet1 = new HashMap<Character, Integer>();
- 泛型声明允许编译器在编译时检查"alphabet1"的使用情况
- 左侧的Map/HashMap声明了应该如何考虑"alphabet1"变量:要么是Map(接口),要么是HashMap(具体类的实例)。当然,接口是首选——它使您的代码对进一步的更改更加健壮
HashMap<Character, Integer> alphabet1 = new HashMap(); // (1)
(1) 在不使用泛型的情况下初始化HashMap
,但随后使用泛型对HashMap
进行不安全的强制转换。这将引发编译器警告。
HashMap<Character, Integer> alphabet1 = new HashMap<Character, Integer>(); // (2)
(2) 用泛型初始化HashMap
,并用泛型声明HashMap
类型的变量。可能人手不足
HashMap<Character, Integer> alphabet1 = new HashMap<>(); // (2b)
这里,编译器使用类型推断来从左手边的声明推断HashMap
的genric。
HashMap alphabet1 = new HashMap<Character, Integer>(); // (3)
(3) 用泛型初始化HashMap,但变量alphabet1
不重用泛型信息。因此,您不能以通用方式访问此HashMap
值上的方法(例如,在调用alphabet1.get('a')
时,您将获得一个转换为java.lang.Object
的值,而不是转换为Integer
)。
Map alphabet1 = new HashMap<Character, Integer>(); // (4)
(4) 类似于(3),但这里alphabet1
是用Map
而不是HashMap
键入的。因此,您不能访问HashMap
中定义的方法,但不能访问其超级接口Map
中定义的。
HashMap alphabet1 = new HashMap(); // (5)
(5) 类似于(3),它不使用泛型来初始化HashMap
。
Map alphabet1 = new HashMap(); // (6)
(6) 类似于(4)并且不使用用于初始化CCD_ 19的泛型。