Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics in HashMap dont seem to be used consistently

Firstly new to Generics. Now question - In the HashMap.java I see the following -

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

Why was this not declared with type parameters ?

Or

 private V getForNullKey() {
        for (Entry<K,V> e = table[0]; e != null; e = e.next) {

Why was Entry in the for loop declared with type parameters?

Is there a deep concept or just an affordable inconsistency ?

like image 398
JavaDeveloper Avatar asked Mar 22 '23 01:03

JavaDeveloper


1 Answers

That's because creating an array of concrete parameterized type is not type safe, and that is why that's not allowed at all.

If you try code something like this, you would get a compiler error:

List<String>[] arr = new ArrayList<String>[10]; // Compiler error: Generic Array creation

The issue is that generic types are non-reifiable - their type information is not available at runtime. Meanwhile, arrays use type information that is available at runtime to do an ArrayStoreCheck to see if an element inserted into an array is compatible with the array's type. So, if you mix up arrays and generics, then you might end up having surprising behaviour at runtime.

For example, consider the following code:

List<String>[] arr = new ArrayList<String>[10];  // Suppose this was valid
Object[] objArr = arr;         // This is valid assignment. A `List[]` is an `Object[]`
objArr[0] = new ArrayList<Integer>();  // There you go. A disaster waiting at runtime.

String str = arr[0].get(0);    // Assigned an `Integer` to a `String`. ClassCastException

So, had the 1st assignment compiled, the 4th assignment, which looks fine to the compiler, would have throw a ClassCastException at runtime.


However, you can create an array of raw types - ArrayList, or unbounded wildcard parameterized type - ArrayList<?>, as both of them are fully reifiable types. So the following array creations are valid:

List[] arr = new ArrayList[10];
List<?>[] arr2 = new ArrayList<?>[10];

Since there is no type information associated with raw types or unbounded wildcard types, there is nothing to lose at runtime. And hence those types are reifiable, they are an eligible component type of an array. That is why Entry[] is used instead of Entry<K, V>[].


See also:

  • How to create a generic array?
like image 198
Rohit Jain Avatar answered Apr 06 '23 07:04

Rohit Jain