views:

180

answers:

3

Hi,

Why doesn't the add() method here compile?

Vector<?> vectorList[] = new Vector<?>[10];
vectorList[0].add("elem1");

Thanks

+3  A: 

There are several problems with your code. Firstly, the elements of the array are uninitialized, and so you are adding to a non-existent vector. And, secondly, adding to a generic container where the type is a wildcard doesn't make sense, because it could be restricted to a more limited type, and so adding would not be safe.

You can fix the first problem, by filling your array:

for (int i = 0; i < 10; i++ ){
    vectorList[i] = new Vector<Integer>(); // can replace Integer with
                                           // any binding for ? 
}

Now that you've seen that it can be filled with vectors that do not accept type String, you can see why the add statement would subsequently fail. You can fix that by binding to a specific type (e.g. String) earlier.

See Java Generics: Wildcards from the Java tutorial for more information.

EDIT
It seems I am doubted, and so I have the following complete, compilable example:

import java.util.*;

public class Main
{
    public static void main(String[] args){
        Vector<?> vectorList[] = new Vector<?>[10];
        for (int i = 0; i < 10; i++ ){
            vectorList[i] = new Vector<Integer>();
        }
        System.out.println("Hello world");
    }
}

Compiling with javac Main.java gives no compilation errors.

Michael Aaron Safyan
This does not compile either (Cannot instantiate the type Vector<?>)
portoalet
@portoalet, did you use ? or a specific type in your new statement?
Michael Aaron Safyan
@portoalet, I've tested it, and I don't have any problems.
Michael Aaron Safyan
i used ? in my new statement
portoalet
@portoalet, well that would explain it, then. You need to bind the wildcard to a particular type when you actually instantiate.
Michael Aaron Safyan
hm ok, so there is no way to leave it as wildcard and compile
portoalet
@portoalet, not without some serious unsafe casting and completely subverting the type system, no.
Michael Aaron Safyan
A: 

Because you have to instantiate each vector in the array, not just the array itself

vectorList[0] = new Vector<?>();
Mike
Even though I instantiated the vector, it still wouldn't compile.
portoalet
see my comment to your post
Mike
+1  A: 

It doesn't compile because vectorList[0] is of type Vector<?>, and you can't call add(T) on a wildcard collection. You can't call add(T) because you can't ensure that the element you are adding is of the (unknown) type that vectorList[0] contains.

The lesson here is that generic types and arrays do not play well together. That is, you can't make vectorList of type Vector<String>[] without an unchecked cast, type Vector[] will give you a raw type to deal with, and you can't do what you want with a Vector<?>[] (the only one that doen't produce a warning). Instead use some List<Vector<String>>.

ILMTitan