Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generics: Why cannot I have Object as parameter for my Collection?

I am going through Generics Tutorial and was going through example to copy objects from array to collection.

Code

    static void fromArrayToCollection(Object[] a, Collection<?> c) {
    for (Object o : a) { 
        c.add(o); // Compile time error
    }
}

I am thinking that I can pass object as parameter to collection and it should work without any issues but tutorial says

By now, you will have learned to avoid the beginner's mistake of trying to use Collection as the type of the collection parameter.

Why does it say that passing Object as parameter type to Collection is not correct approach? Updated:

    static void fromArrayToCollection(Object[] a, Collection<Object> c) {
    for (Object o : a) { 
        c.add(o); // Compile time error
    }
}
like image 279
Rachel Avatar asked Feb 24 '23 13:02

Rachel


1 Answers

The "beginner mistake" they're referring to is saying Collection<Object> when what you were trying to say is "any Collection/Collection of Anything." It would in the abstract be perfectly legal to declare the method as Collection<Object> it just doesn't meet the design goal of a method that takes in anything.

We want to be able to do this:

public static void main(String[] args) {
    String[] stringArray = {"A", "B", "C"};
    List<String> stringList = new ArrayList<String>();
    fromArrayToCollection(stringArray, stringList);
    Integer[] intArray = {1, 2, 3};
    List<Integer> intList = new ArrayList<Integer>();
    fromArrayToCollection(intArray, intList);
}

public static <T> void fromArrayToCollection(T[] array, Collection<T> collection) {
    for (T item: array) {
        collection.add(item);
    }
}

That wouldn't work if you made it Collection<Object>.

You can't declare the parameter type as Collection<Object> and have it work for multiple types like above because generic types aren't covariant. It would be illegal to say, pass in List<String> to a method with an argument type of Collection<Object>. A Collection<String> is not a Collection<Object>.

Consider the standard example:

List<Integer> intList = new ArrayList<Integer>();
List<Object> objList = intList; //doom impending!!!
objList.add("NOTANUMBER");
int i = intList.get(0).intValue(); //runtime exception!

That's why it's illegal to declare it as Collection<Object> and take a collection of anything.

like image 198
Affe Avatar answered Feb 26 '23 04:02

Affe