这些初始化HashMap的方法之间有什么区别?



我在程序中使用了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();

任何涉及HashMapMap但没有类型参数(尖括号<和>以及它们之间的部分)的内容都是原始类型,不应使用。原始类型不是泛型的,它允许您执行不安全的操作。

"正确"的方法是

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>();
  1. 泛型声明允许编译器在编译时检查"alphabet1"的使用情况
  2. 左侧的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的泛型。

最新更新