繁体   English   中英

HashMap实现中的泛型

[英]Generics in HashMap implementation

在Java实现中,我发现

 transient Entry[] table; 
 which is initiated in constructor as
 table = new Entry[capacity];

我知道并了解不允许创建通用数组,但是我无法理解的是整个过程是如何工作的。 我的意思是当我们做类似的事情时

HashMap<Integer, String> hMap = new HashMap<Integer, String>();

上面的代码如何导致创建类型为<Integer, String>的Entry数组

好吧,很少有人无法理解我的要求。 改写我要问的是做这样的事情有什么意义

HashMap<Integer, String> hMap = new HashMap<Integer, String>();

当它不导致

Entry<Integer, String>

泛型是编译时的安全性。 在运行时,地图仅了解对象。 这称为类型擦除 为了进一步吓到您,以下代码将毫无问题地运行:

Map<Integer, Integer> safeMap = new HashMap<>();
Map unsafeMap = safeMap;
unsafeMap.put("hello", "world");

您将在编译时收到警告,因为您使用的是原始Map而不是通用Map,但在运行时根本不执行任何检查,因为该Map是可以存储任何对象的良好旧Map。 只有编译器才能阻止您在映射或整数中添加字符串。

该实现使类型为Entry<K,V>对象数组

static class Entry<K,V> implements Map.Entry<K,V>

而不提供通用类型参数( source )。 这是允许的,但要理解编译器不再保证类型安全。 例如,在代码的其他地方,您可以编写

Entry<K,V> e = table[bucketIndex];

编译器将允许您执行此操作。 如果您确定始终将table[]元素设置为nullEntry<K,V> ,则可以知道分配是正确的。

这样做没有问题的原因是Java中的泛型类型是通过类型擦除实现的,即Entry<K,V>对象Entry<Integer,Integer>Entry<String,Long>在运行时没有区别。

尝试以这种方式思考Java泛型:类型参数仅适用于引用类型的表达式静态类型,不适用于在运行时引用值所引用的实际实例类型

在阅读Java代码时,我发现了开发正确直觉的上述关键。 所以下次你看到

new HashMap<Integer, String>()

读如下:“这是类型为HashMap<Integer, String>的实例创建表达式。在运行时,该表达式将产生对HashMap类实例的引用。” 只要编译器可以精确地跟踪您对该表达式结果的处理方式,它就可以保持知道确实是HashMap<Integer, String> ,但是HashMap<Integer, String>

现在,由于静态类型系统的功能不足以跟踪数组的组件类型上的类型参数(Java的数组类型是协变量的事实在这里发挥了重要作用),因此代码被迫脱离静态类型安全网络。 关键的观察是,这本身并不会使代码不正确 ,而只会限制编译器发现编程错误的能力。 这就是为什么Java允许您从原始类型到泛型类型进行未经检查的强制转换,尽管并非没有警告,这标志着您已经离开了静态类型安全的省份。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM