3

Possible Duplicate:
Java: Array of primitive data types does not autobox

I've been doing some Java lately (mostly as a recap on what I did at university as my current job doesn't involve any Java at all) and one thing that never got introduced to us properly is Generics.

I've been doing the Generics tutorial on the Oracle Java website and I've been stumped by the following example that I modified a bit:

public static <Integer extends Comparable<Integer>> int countGreaterThan(Integer [] anArray, Integer elem) {
    int count = 0;
    for (Integer e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
        return count;
}

And I use this method to compare an Integer array with the following Integer:

Integer [] numarr = {1, 2, 3, 4 , 5};
Integer num = new Integer(5);

int count = Util.countGreaterThan(arrnum, num);

This seems to work fine, however if I pass a primitive array and a primitive int, it doesn't:

int [] arrnum = {1, 2, 3, 4 , 5};
int othernum = 3;

int count = Util.countGreaterThan(arrnum, othernum);

The compiler complains with:

method countGreaterThan in class Generics.Util 
cannot be applied to given types;
required: Integer[],Integer
found: int[],int
reason: no instance(s) of type variable(s) 
Integer exist so that argument type int conforms to formal parameter type Integer

The tutorials seemed to be pretty adamant that Java will always autobox/unbox objects and primitives as necessary and yet it won't do it in this particular case, what am I missing?

Also what could be a good way to generalise this comparing method as much as possible? If I used T instead of Integer, then it would look for a T object, rather than whatever I pass to it.

I apologise if the post is confusing and if I seem pretty ignorant about the stuff I talk about above, it's just that I've been working primarily as a perl programmer (and not as particularly experienced one either) and generalising there seems as less of an issue (due to the lack of type enforcement).

Thanks in advance!

4

2 回答 2

1

The code below seems to work as far as I can see:

public static <Integer extends Comparable<Integer>> int countGreaterThan(Integer [] anArray, Integer elem) {
    int count = 0;
    for (Integer e : anArray) {
        if (e.compareTo(elem) > 0)
            ++count;
        return count;
}

although I get a warning "The type parameter Integer is hiding the type Integer". See @ErichSchreiner's answer for an explanation of why auto-boxing won't work here.

A good generalisation of your method would be:

public static <T extends Comparable<? super T>> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray) {
        if (e.compareTo(elem) > 0) {
            ++count;
        }
    }
    return count;
}

All you really care about is that anArray has the same type of elements as elem is, and that it is comparable to it's own type.

于 2012-07-11T08:27:42.980 回答
1

Your declaration of countGreaterThan() hides the built-in type Integer. To clarify, consider the slightly modified version:

public static <I extends Comparable<I>> int countGreaterThan(I [] anArray, I elem) {
    int count = 0;
    for (I e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
        return count;
}

Now it should become apparent that your second attempt at calling can not work as there can be no autoboxing done. For generics to work, you need to supply objects, not primitives.

于 2012-07-11T08:28:28.880 回答