【问题标题】:Java EnumMap Parameter confusionJava EnumMap 参数混淆
【发布时间】:2014-02-28 19:55:35
【问题描述】:

我第一次使用 EnumMap,不明白参数传递实际上在做什么。据我所知,它只是“K.class”,其中 K 是映射键。这工作得很好,但我在 Java 的其他任何地方都没有看到过,而且我不清楚它在构造中实际扮演什么角色。

我猜这是一个理论上的问题,因为代码运行:“K.class”参数是什么意思,EnumMap 需要它做什么?

【问题讨论】:

  • 哪部分不明白?
  • <K, V> 将在编译器应用类型擦除后从 Map<K, V> 消失。但是,在运行时,Map 实现需要确切地知道你在说什么枚举类。所以你必须指定类。

标签: java enum-map


【解决方案1】:

查看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。当您将它传递给put() 时,它没有存储对 Enum1.V1 的引用。但是,get 方法现在需要知道传递的值不属于正确的枚举,因此映射中没有此键的值。这里也需要正确枚举的类型,为此您需要将类型传递给构造函数。

如果不向构造函数提供有关枚举的一些信息,它就不会知道您打算将哪个枚举用于此地图实例。即使你写了新的EnumMap&lt;MyEnum, SomeValue&gt;(),由于类型擦除,构造函数也无法知道泛型类型参数的值MyEnum。因此需要另一种方式将信息传递给构造函数。

【讨论】:

  • 谢谢你,我现在关注。我熟悉泛型,这意味着许多其他 cmets 和其他地方的讨论都没有帮助。我只是对类文字很熟悉,所以我不明白需要一个,因为我没有考虑过类型擦除会阻止仅检查键类型。
【解决方案2】:

基于EnumMap 的来源:看来,当您构造EnumMap 时,它所做的第一件事就是分配一个数组,该数组对于enum 类中的每个枚举常量都有一个元素。 EnumMap 应该是高效的,所以它会分配一个固定的数组是有道理的。为此,它需要知道类。如果不是类型擦除,这可以通过查看K.class 来完成,其中K 是EnumMap&lt;K,V&gt; 中的第一个类型参数。不幸的是,Java 泛型的设计阻止了这一点。

【讨论】:

  • 在查看实现之前,应该首先检查规范。它说“枚举映射在内部表示为数组。”
猜你喜欢
  • 2013-05-23
  • 2023-03-03
  • 2017-04-15
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多