我第一次使用EnumMap,并且不明白参数传递实际上在做什么。据我所知,它只是“K.class”,其中K是地图键。这很好用,但我还没有在Java的其他任何地方看到这个,我不清楚它在构造中的实际作用。
我想这是一个理论问题,因为代码运行:“K.class”参数意味着什么,以及EnumMap需要什么?
答案 0 :(得分:8)
请参阅class literals的链接问题。
EnumMap
特别需要它,因为它需要知道枚举有多少不同的值。这是因为EnumMap是一个高度优化的枚举映射实现,它只使用一个数组,每个可能的值都有一个插槽(而不是像HashMap那样更大的数组)。当你调用get()
时,它会检索给定键的索引(即第一个枚举值,第二个等)并查看其内部数组的适当位置。为此,构造函数需要知道分配正确大小的数组的可能值的数量。
给定类对象,它可以调用getEnumConstants()
来查找此枚举的现有值的数量。
此外,想象下面的代码:
enum Enum1 { V1, V2; }
enum Enum2 { W1, W2; }
EnumMap<Enum1, Object> map = new EnumMap<Enum1, Object>(Enum1.class);
map.put(Enum1.V1, new Object());
map.get(Enum2.W1);
现在get
方法显然应该返回null
。但是,正如我所说,地图内部只有一个数组,在这种情况下大小为2,新对象在第一个插槽中,null在第二个插槽中。当您将Enum1.V1传递给put()
时,它没有存储对Enum1.V1的引用。但是,方法get
现在需要知道传递的值不属于正确的枚举,因此映射中没有此键的值。这里也需要正确枚举的类型,为此你需要将类型传递给构造函数。
如果没有向构造函数提供有关枚举的一些信息,它就不会知道您打算使用哪个枚举这个地图实例。即使您编写新的EnumMap<MyEnum, SomeValue>()
,由于类型擦除,构造函数也无法知道泛型类型参数的值MyEnum
。因此,需要另一种方法将信息传递给构造函数。
答案 1 :(得分:2)
基于EnumMap
的来源:看来,当你构造一个EnumMap
时,它首先做的事情之一是分配一个数组,该数组在{的每个枚举常量中都有一个元素{1}}课程。 enum
应该是有效的,所以它将分配一个固定的数组是有道理的。要做到这一点,它需要知道这个类。如果不是类型擦除,可以通过查看EnumMap
K.class
K
中EnumMap<K,V>
中的第一个类型参数来完成。不幸的是,Java泛型的设计阻止了这一点。