1

I have the class:

class SomeClass<T extends SomeInterface>{

   private T[] myArray;

   public SomeClass()
   {
       // I want to initialize myArray in here to a default size of 100
       myArray = new T[100];  // this gives an error
   }

}

I know I can fix that by requiring a parameter in the constructor as:

class SomeClass<T extends SomeInterface>{

   private T[] myArray;

   public SomeClass(Class<T> clazz)
   {       
       myArray= (T[]) Array.newInstance(clazz, 100);
   }

}

but it makes no scene having to pass the generic parameter twice.

in other words in order to instantiate an object from the class SomeClass I will have to do something like:

SomeClass<SomeOtherClass> obj = 
      new SomeClass<SomeOtherClass>(SomeOtherClass.class);

I program in c# and Java does not seem to be friendly. I don't even understand why it is not possible to cast Object[] array to SomeOtherClass[] array. In c# that will be possible...

so my question is how can I avoid having to pass the SomeOtherClass.class parameter in order to be able to construct an array of the generic type in the constructor of the class...

Bhesh Gurung
  • 48,464
  • 20
  • 87
  • 139
Tono Nam
  • 29,637
  • 73
  • 252
  • 421
  • 1
    possible duplicate of [What's the reason I can't create generic array types in Java?](http://stackoverflow.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java). And see [this](http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html). – Dave Newton Dec 11 '11 at 02:35
  • 1
    As much as I love Java, C#'s implementation of generics is better than Java's since it was part of the C# language from the very beginning, and there was no need to worry about backwards compatibility causing Java's type erasure issues. – Hovercraft Full Of Eels Dec 11 '11 at 02:38
  • The Intermediate Language (IL) implementation is not better, it's different. The IL implementation is actually more restrictive compared to Javas byte code making some language constructs (by other languages that run on the CLR/DLR) impossible. So there is actually a downside to the IL implementation. – M Platvoet Dec 11 '11 at 06:49

3 Answers3

4

While Shakedown listed the fix to your problem, allow me to explain why it is not typesafe to create a generic array.

I will illustrate why with an example from Effective Java 2nd Ed.

// Why generic array creation is illegal - won't compile! 
List<String>[] stringLists = new List<String>[1]; // (1) 
List<Integer> intList = Arrays.asList(42); // (2) 
Object[] objects = stringLists; // (3) 
objects[0] = intList; // (4) 
String s = stringLists[0].get(0); // (5)
  • Let’s pretend that line 1, which creates a generic array, is legal.

  • Line 2 creates and initializes a List<Integer> containing a single element.

  • Line 3 stores the List<String> array into an Object array variable, which is legal because arrays are covariant.

  • Line 4 stores the List<Integer> into the sole element of the Object array, which succeeds because generics are implemented by erasure: the runtime type of a List<Integer> instance is simply List, and the runtime type of a List<String>[] instance is List[], so this assignment doesn’t generate an ArrayStoreException. Now we’re in trouble. We’ve stored a List<Integer> instance into an array that is declared to hold only List<String> instances.

  • In line 5, we retrieve the sole element from the sole list in this array. The compiler automatically casts the retrieved element to String, but it’s an Integer, so we get a ClassCastException at runtime. In order to prevent this from happening, line 1 (which creates a generic array) generates a compile-time error.

Adrian
  • 5,416
  • 7
  • 45
  • 78
  • This example fails to prove anything, as an otherwise identical example written using a generic _collection_ compiles and runs (generating a ClassCastException), but this example, written using a generic _array_ doesn't compile. Yet another glaring inconsistency in generic Java, for no clear reason. – Clement Cherlin May 05 '20 at 21:05
1

Yes, you would have to pass in the .class like that in order to make this work.

You could avoid all of this and just use an ArrayList<T> instead. When you need it in the form of an array you can use: (T[]) myArrayList.toArray()

Nate W.
  • 8,631
  • 6
  • 38
  • 65
  • "When you need it in the form of an array you can use: (T[]) myArrayList.toArray()" if you return that to code outside of the class it will throw an exception. it is no different than `(T[])new Object[100]` – newacct Dec 13 '11 at 21:41
0

All and every type in java is a subclass of Object class so this can be achieved using this.

public StackArray(int size){
    dataStack = (T[])new Object[size];
}
Keavon
  • 5,460
  • 7
  • 43
  • 72