-3

I realized in Java, to do generic array, this is what "some" people do (because it works in some cases):

How to create a generic array?

Those answers (or other online answers) generally say there are two ways of doing it, one is do type conversion for Object[], the other is to use Arrsy.newInstance(), a reflection, But reflection requires import Java.reflect.. etc. which i probably can not do now (for restriction reasons).

MyType[] newArray = (MyType[]) new Object[size];

But, I got error at runtime:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LMyClass$MyType;

As you have seen, MyType is a private class defined in MyClass. Also, MyClass is defined as :

class MyClass<K,V> {
    private class MyType {
       public K data;
       public V data;
    }
    pass;
}

I guess the casting failed because of: 1, nested class definition 2, generic type in the nested definition?

Could anyone shine light on this issue? thx

Community
  • 1
  • 1
bozeng
  • 225
  • 1
  • 2
  • 10

3 Answers3

1

This is not what people do. What people do is:

public <T> T[] createArray(Class<T> clazz , int capacity){
     return (T[]) Array.newInstance(clazz , capacity);
}

Your creating an array of objects an expecting java to accept it as array of T. Which obviously doesn't work (for a reason). Basically what the cast (T[]) new Object[] is as if i gave you a pizza and told you to use it as TV-remote. If this would work, this would be possible:

Object[] objArr = new Object[2];
objArr[0] = "abc";
objArr[1] = 23;

//lets assume the cast works.
String[] strArr = (String[]) objArr;
//what to do here? objArr[1] should be String, but
//is Integer -> no charAt
System.out.println(objArr[1].charAt(0));
Paul
  • 13,100
  • 3
  • 17
  • 34
  • those answers generally say there are two ways of doing it, one is do type conversion for Object[], the other is reflection, as you wrote..but reflection requires import Java.reflect.. etc. which i probably can not do now(for restriction reasons) – bozeng Mar 25 '15 at 06:22
  • the way with Object[] can't work. i'll edit the answer to show why. – Paul Mar 25 '15 at 12:45
1

You just misunderstood that: In clause MyType[] newArray = (MyType[]) new Object[size];, MyType does not represent a class identifier but a type parameter, which is to be declared like this YourClass<YourType>. Generic array creation is something like this:

new K[length];
new V[length];

which is not allowed in java (where as generic array declaration (K[] genericArray) is allowed). So you need to get around this limit with

K[] genericArray = (K[]) new Object[length];

which will lead to warning of compiler. Use @SuppressWarning("unchecked") to get rid of that.

This is not quite safe, so don't let that exposed to client codes.

Use Paul's answer whenever possible, since it is more safe. (The reason is here How to create a generic array in Java?). Use the unsafe solution mentioned above only when you cannot get or determine the runtime class of the element of the array to be created. For example, in a definition of a parameterized class, you cannot get the runtime class of the type parameter, which only functions during compilation and will be erased after that, (something like E.class won't compile), you have to use the unsafe workaround.

Community
  • 1
  • 1
charlieh_7
  • 193
  • 2
  • 10
  • but actually if i use class Dog {} and Dog[] genericArray = (Dog[]) new Object[length]; it works. K, V are not just types . – bozeng Mar 25 '15 at 06:28
  • `public class Main { public static class E{} public static void main(String[] args) { E[] arr = (E[]) new Object[5]; Arrays.toString(arr); } }` Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Lgrid.Main$E; at grid.Main.main(Main.java:21) – charlieh_7 Mar 25 '15 at 11:00
0

When you use new to create an array, the component type must be a reifiable type. MyType is a non-static inner class of MyClass, so when you write MyType without any qualification inside MyClass, it implicitly means MyClass<K,V>.MyType, a parameterized type.

Generally, in this situation of creating an array of a parameterized type (note: this is very different from questions about creating an array of a type parameter type; MyType is not a type parameter), one would create an array of the raw type or the wildcard-parameterized type (both of which are reifiable), and the convert to the type of array of the parameterized type:

MyType[] newArray = new MyClass.MyType[size];

(Note that the raw type is not just MyType, as we noted above that this is MyClass<K,V>.MyType. To get the raw type we must explicitly qualify it with the raw MyClass.)

or

MyType[] newArray = (MyType[])new MyClass<?>.MyType[size];
newacct
  • 110,405
  • 27
  • 152
  • 217