-2

As a class assignment, I have to implement a custom implementation of AbstractCollection, and to make use of generics. I found out that AbstractCollection.toArray() hides its default T type as follows:

public <T> T[] toArray(T[] a) { ... }

I initially thought the following would work, but I'm being told by my IDE that it won't override the super:

@Override
public T[] toArray(T[] a) { ... }

So, then I add <T> to the method signature, and now (although it will compile) am being told the following:

Array of type 'T[]' expected

//Reports two types of suspicious calls to Collection.toArray().
//The first type is any calls where the type of the specified array argument
// is not of the same type as the array type to which the result is casted.
//Example:
void m(List list) {
  Number[] ns = (Number[])
      list.toArray(new String[list.size()]);
}
//The second type is any calls where the type of the specified array argument doesn't match
// the type parameter of the collection declaration.
//Example:
void m(List<Number> list) {
  Number[] ns =
      list.toArray(new String[list.size()]);
}

So, my first question is, is there a good reason why it's done this way to begin with? And secondly, will this affect my implementation in any way?

River
  • 8,585
  • 14
  • 54
  • 67
Mirrana
  • 1,601
  • 6
  • 28
  • 66
  • Would any of the negative nancies care to explain to me why they downvoted this question? I don't see anything wrong with it. – Mirrana Feb 16 '16 at 17:54
  • When you give a `String[]` to the `toArray()` method, the return value is a `String[]`, and that is incompatible with `Number[]`. If you want `Number[]`, give that as argument. – Andreas Feb 16 '16 at 17:54
  • 1
    Are you looking for http://stackoverflow.com/q/9874121/869736 ? – Louis Wasserman Feb 16 '16 at 17:58
  • @LouisWasserman Not quite, but it may be of relevance. Thanks – Mirrana Feb 16 '16 at 18:08
  • 1
    @agent154 that's pretty much an answer to your first question -- `toArray` is written that way because the collection doesn't know _how_ to create an array of the appropriate type. – Louis Wasserman Feb 16 '16 at 18:09
  • @LouisWasserman Well, it explains why you have to pass in an array, to be updated if large enough, or as a template if not. It doesn't explain why the method adds a `` instead of using the already defined ``. I've tried to answer that in [my answer](http://stackoverflow.com/a/35439811/5221149). – Andreas Feb 16 '16 at 18:11

1 Answers1

1

The Collection interface declares the method as:

<T> T[] toArray(T[] a)

so you must do the same in the implementing class, otherwise it's not an override of the given method, but instead a overload.

It was done that way for backwards compatibility, since the method existed before generics were added to the language. The official 1.4 documentation is no longer available online, but you can find it here (for now): https://www.cs.duke.edu/csed/java/jdk1.4.2/docs/api/java/util/Collection.html#toArray%28java.lang.Object[]%29

Remember, List<Number> and List<Integer> is really just a List at runtime, because of type erasure. The distinction is done at compile time. On the other hand, Number[] and Integer[] are actually distinct at runtime, and will throw an exception if the value is of the wrong type.

This means that you can create a Number[] from a List<Integer>, if you choose. You can even create an Integer[] from a List<Number>, if you are sure that all list elements are actually Integer objects.

Andreas
  • 154,647
  • 11
  • 152
  • 247