Consider the following code example:
@SafeVarargs
public static <U> Object[] sortedCopy(Comparator<? super U> comparator, U... values) {
U[] copy = Arrays.copyOf(values, values.length);
Arrays.sort(copy, comparator);
return copy;
}
public static <U> Object[] sortedCopy(U... values) {
return sortedCopy(Comparator.naturalOrder(), values);
}
I expected the compiler to reject the string in sortedCopy(U...), with the following considerations:
The return type Comparator.naturalOrder()is Comparator<T>, where Tis the parameter of the general type of this method, which must fulfill the restriction T extends Comparable<? super T>. Since the method does not accept any arguments, and its call in the above code does not explicitly indicate the type for T(for example Comparator.<U>naturalOrder(), which does not compile because it Udoes not extend Comparable), it Tmust be deduced in a different way. The only way I can infer Tis by method signature sortedCopy(Comparator<? super U>, U...). The compiler knows the type valuesand therefore can output Uand, in turn, can also derive estimates for T, namely, a limited wildcard ? super U. But then the compiler must understand that any? super Ucannot satisfy the requirement for T, indicated Comparator.naturalOrder(), which T extends Comparable<? super T>, because it Udoes not expand itself Comparable<? super U>, therefore, any supertype Ucannot either.
What bothers me is that the compiler generates an error when I change the signature from sortedCopy(U...)to sortedCopy(U[]). I believe that this is due to the fact that in the second case it is Upresent at run time as an array type, whereas in the first case it is not. But I still don't understand why this would make the method call valid, because:
- , varargs
Object[], , vararg, , , , , , , U sortedCopy(U...) . , , Object Comparable<? super Object>? - . , - , , ,
U , , , vararg.
, , ?
, , @SafeVarargs sortedCopy(Comparator<? super U>, U...) . , , .