Reputation: 51
I'd like to iterate over a collection being passed in to a generic method like so:
public <T> int oddNumberCounter(T collectionOfNums) {
int count = 0;
Iterator<Integer> integerIterator = collectionOfNums.iterator();
while(integerIterator.hasNext()) {
int current = integerIterator.next();
if (oddNumberCheck(current))
count++;
}
return count;
}
However, it seems like collectionOfNums is not being picked up as a collection as I think it should do. Is this a valid thing to do, if not, what would be the best way to go about it?
Upvotes: 0
Views: 401
Reputation: 102968
collectionOfNums is not being picked up as a collection as I think it should do.
You've decreed that this method has a type variable (that is what the <T>
is about), and that this type variable has absolutely nothing known about it (otherwise you'd have written <T extends Number>
for example). Why would java infer that T must therefore be a collection? Generics has (almost) nothing to do with inference. Perhaps you think generics are inherently related to collections. Or perhaps your thinking is: Hey, I call iterator()
on it later, and that is a method only collections have (that's false, by the way). This isn't how it works; generics are for anywhere you need to parameterize types. Collections is just one of many things that like that.
In basis you could do this:
public <T> int oddNumberCounter(Collection<T> collectionOfNums) {
...
}
but this still isn't what you want: Generics serve to link types together. If you use a type variable in exactly one spot it is completely useless. So, the above is useless. Instead, you'd write:
public int oddNumberCounter(Collection<?> collectionOfNums) {
...
}
except that still isn't what you want: It's right there in the name, you want a collection of numbers. So, add a type bound:
public <T extends Number> int oddNumberCounter(Collection<T> collectionOfNums) {
....
}
except we can simplify that and get rid of the T, going back to the question mark usage (it's still the case that the letters serve to link types, and we're still only using it once, therefore, useless). Putting it all together:
public int oddNumberCounter(Collection<? extends Number> collectionOfNums) {
int count = 0;
for (Number n : collectionOfNums) {
if (n.intValue() % 2 != 0) count++;
}
return count;
}
Note that this considers e.g. 5.2
(the double) as 'odd', because its intvalue is '5', and that is odd. I'm pretty sure you really want Collection<Integer>
instead, and no generic bounds whatsoever.
This is different from Collection<Number>
, in that you can invoke this method and pass in e.g. an ArrayList<Integer>
, or a LinkedList<Double>
, etcetera.
Upvotes: 2
Reputation: 19
You can define the generic parameter as <? extends Collection> so the Java compiler knows it must accept a collection.
Upvotes: -1