52

I don't understand the error of Generic Array Creation.
First I tried the following:

  public PCB[] getAll() {
       PCB[] res = new PCB[list.size()];
           for (int i = 0; i < res.length; i++) {
               res[i] = list.get(i);
            }
       list.clear();
       return res;
}


Then I tried doing this:

PCB[] res = new PCB[100];


I must be missing something cause that seems right. I tried looking it up I really did. And nothing is clicking.


My question is: What can I do to fix this?


the error is :

.\Queue.java:26: generic array creation
PCB[] res = new PCB[200];
            ^
Note: U:\Senior Year\CS451- file      
uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

Tool completed with exit code 1

6
  • Can you post the Exception/Error Commented Oct 5, 2010 at 17:08
  • 2
    I am assuming that PCB is a generic type parameter and thus, what you are doing is impossible in Java due to type-erasure. If that is all true, you should click on the link I marked this a dup of as it provides a workaround. Commented Oct 5, 2010 at 17:14
  • already tried reading that post. it doesn't help me Commented Oct 5, 2010 at 17:24
  • 3
    the sad truth is that Java made the conscious decision to explicitly prevent this syntax from working. Java implements type-erasure, which means that the type argument PCB actually has no meaning at runtime (or technically, it does, but it's probably just Object which wouldn't do you any good). There are two ways to circumvent this restriction. Both are explained in detail at the link I referenced. Let me know what specific part of that solution you are having trouble with. Commented Oct 5, 2010 at 17:35
  • 2
    PCB<?>[] res = new PCB<?>[100]; is possible Commented Feb 11, 2016 at 7:42

3 Answers 3

55

You can't create arrays with a generic component type.

Create an array of an explicit type, like Object[], instead. You can then cast this to PCB[] if you want, but I don't recommend it in most cases.

PCB[] res = (PCB[]) new Object[list.size()]; /* Not type-safe. */

If you want type safety, use a collection like java.util.List<PCB> instead of an array.

By the way, if list is already a java.util.List, you should use one of its toArray() methods, instead of duplicating them in your code. This doesn't get you around the type-safety problem though.

Sign up to request clarification or add additional context in comments.

8 Comments

yea but when you return it to the outside, and the caller assigns it to a variable of type PCB[]. boom you will get a class cast exception
@newacct - That won't necessarily happen. It depends on the calling context. But it can happen. That's what I meant by "Not type-safe," and why I recommended against it.
@erickson: It will eventually happen at some point as the recursion unfolds. Generics always become concrete at some point or else no work would ever get done. The only way this would reasonably work is if the result is never actually used as an array of the actual type of PCB. In which case it's much better to just declare yourself as returning an Object[].
@erickson: Exactly, and since that's the case, then just return an Object[] since it's type-safe and doesn't limit usage at all. Any usage that uses the result as anything but an Object[] is basically guaranteed to throw a runtime error, so why the heck would you bother returning anything else?
@erickson, actually, I found a usage example where it's not strictly stupid. If the generic array remains encapsulated in a collection (ArrayList, e.g.) then access to and from the array is performed through generics alone and it works. Wasn't thinking of keeping it around as an instance variable.
|
5

The following will give you an array of the type you want while preserving type safety.

PCB[] getAll(Class<PCB[]> arrayType) {  
    PCB[] res = arrayType.cast(java.lang.reflect.Array.newInstance(arrayType.getComponentType(), list.size()));  
    for (int i = 0; i < res.length; i++)  {  
        res[i] = list.get(i);  
    }  
    list.clear();  
    return res;  
}

How this works is explained in depth in my answer to the question that Kirk Woll linked as a duplicate.

Comments

3

Besides the way suggested in the "possible duplicate", the other main way of getting around this problem is for the array itself (or at least a template of one) to be supplied by the caller, who will hopefully know the concrete type and can thus safely create the array.

This is the way methods like ArrayList.toArray(T[]) are implemented. I'd suggest you take a look at that method for inspiration. Better yet, you should probably be using that method anyway as others have noted.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.