The problem of generic arrays (i.e., the impossibility of them) seems to be a recurring theme for me. Below is the relevant code of a HashMap data structure. Obviously, I cannot declare a Bucket[], since generic arrays are impossible. However, I can declare a MapThing.Bucket[]. Am I correct when I assert that this is good practice, since even though MapThing.Bucket[] is a raw type declaration, the actual MapThing.Bucket[] instance is type parameterized by its enclosing instance?
Thanks for any insight!!!
Chris
public class MapThing<K, V> {
private Bucket buckets[];
public static void main(String[] argv) {
MapThing<String, Integer> thing = new MapThing<>();
thing.put("got your number", 8675309);
}
@SuppressWarnings("unchecked")
public MapThing() {
buckets = new MapThing.Bucket[314159];
}
public void put(K key, V value) {
Bucket bucket = new Bucket(key, value);
// Prints typeof bucket key: String, value: Integer
System.out.println("typeof bucket key: "
+ bucket.getKey().getClass().getSimpleName() + ", value: "
+ bucket.getValue().getClass().getSimpleName());
buckets[Math.abs(key.hashCode() % buckets.length)] = bucket;
}
private class Bucket {
private K key;
private V value;
Bucket(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() {
return key;
}
public V getValue() {
return value;
}
}
}
You can ALWAYS declare a variable of any array type. Always. It is perfectly fine to declare variables of
Bucket[]orArrayList<String>[]or whatever.You cannot use the array creation expression (i.e.
new X[...]) with a parameterized type (i.e. ifXisSomething<SomethingElse>whereSomethingElseis anything except?). You can use array creation expression with a raw type (i.e.new X[...]whereXis a raw type), e.g.new ArrayList[10].Therefore, if
Bucketwere a raw type, thennew Bucket[10]would be perfectly fine. The thing is,Bucketis not a raw type.Bucketis a non-static inner class inside a generic outer class. That means it is within the scope of the type parameters of its outer class. In other words, if you write the unqualified typeBucketinsideMapThing, it implicitly meansMapThing<K,V>.Bucket, which is a parameterized type.To get the raw type, you need to explicitly qualify it with the outer class, as in
MapThing.Bucket. Sonew MapThing.Bucket[10]will work.Alternately, if you don't want to use raw types, you can parameterize it with all wildcards:
new MapThing<?,?>.Bucket[10].