Generics in HashMap implementation

后端 未结 3 529
北海茫月
北海茫月 2021-01-26 17:49

In the Java implementation, I found

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

I know and u

相关标签:
3条回答
  • 2021-01-26 18:10

    Generics are a compile-time safety. At runtime, the map only know about Objects. This is known as type erasure. To scare you even more, the following code will run without problem:

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

    You'll get a warning at compile time, because you're using a raw Map instead of a generic one, but at runtime, no check is done at all, because the map is a good old map able of storing any object. Only the compiler prevents you from adding Strings in a map or integers.

    0 讨论(0)
  • 2021-01-26 18:10

    Try to think of Java Generics this way: type parameters only apply to the static type of reference-typed expressions and do not apply to the type of actual instances being referred to by the reference values at runtime.

    I find the above key to developing the proper intuitions when reading Java code. So the next time you see

    new HashMap<Integer, String>()
    

    read it as follows: "This is an instance creation expression of the type HashMap<Integer, String>. At runtime this expression will yield a reference to an instance of the HashMap class." As long as the compiler can precisely track what you do with the result of that expression, it can maintain the knowledge that this is indeed a HashMap<Integer, String>, but no further than that.

    Now, since the static type system is not powerful enough to track the type parameters on the component type of arrays (the fact that Java's array types are covariant plays strongly here), the code is forced to break out of the static type safety network. The key observation is that on its own, this does not make the code incorrect, it only constrains the power of the compiler to find programming mistakes. This is why Java allows you to make unchecked casts from raw into generic types, although not without a warning which marks the spot where you have left the provinces of static type safety.

    0 讨论(0)
  • 2021-01-26 18:19

    The implementation makes an array of Entry<K,V> objects of type

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

    without providing generic type parameters (source). This is allowed, but it comes with understanding that the compiler is no longer guarantees type safety. For example, in other places in code you could write

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

    and the compiler will let you do that. If you know for sure that you always set elements of table[] to null or Entry<K,V>, then you know that the assignment is correct.

    The reason this works without a problem is that generic types in Java are implemented through type erasure, i.e. there is no difference at runtime between Entry<K,V> objects Entry<Integer,Integer> and Entry<String,Long>.

    0 讨论(0)
提交回复
热议问题