泛型类型变量的局部类型推断与逆变性技术咨询
Great question! Let's break this down clearly—starting with how local variable type inference (LVTI) works in your rewrite, then unpacking the contravariance details tied to your generic method.
1. Rewriting the Method with Local Variable Type Inference
First, here's how you can rewrite your method using var to leverage LVTI, while preserving all the original functionality:
public static <T> Set<T> distinct(Collection<? extends T> list, Comparator<? super T> comparator) { var set = new TreeSet<>(comparator); // LVTI infers TreeSet<T> automatically set.addAll(list); return set; }
The compiler has no trouble inferring that set should be of type TreeSet<T> here. Why? Because:
- The
TreeSetconstructor accepts aComparator<? super E>, whereEis the type of elements in the set. - Your method's
comparatorparameter is typed asComparator<? super T>, and you're adding elements fromCollection<? extends T>to the set. The compiler ties these constraints together to deduce thatEmust beT, sovarresolves toTreeSet<T>—which is perfectly compatible with the return typeSet<T>.
2. Contravariance in the Comparator Parameter
Let's dive into the contravariance aspect of your original method's Comparator<? super T> parameter:
- Contravariance (using
? super T) allows your method to accept any comparator that can handle T or its parent types. This makes the method far more flexible: for example, ifTisString, you could pass aComparator<Object>(sinceObjectis a supertype ofString, and the comparator'scomparemethod can acceptStringinstances via polymorphism). - When using LVTI, this contravariance is fully respected. The compiler doesn't lose track of the
? super Tconstraint on the comparator—it uses it to validate that the comparator is compatible with the inferredTreeSet<T>type. SinceTreeSet<T>expects aComparator<? super T>, your input parameter fits perfectly.
3. Key Notes & Edge Cases
- You don't need to explicitly specify the type parameter for
TreeSet(likenew TreeSet<T>(comparator)) when usingvar—the compiler's inference is reliable here, thanks to the constraints from both thelistandcomparatorparameters. - If you ever run into edge cases where type inference is ambiguous (rare here), you can always fall back to explicitly specifying the type parameter, but that's unnecessary for your current method.
- The original method's use of
Collection<? extends T>(covariance) pairs nicely with the contravariant comparator: it lets you pass any collection of T subtypes (likeArrayList<String>whenTisCharSequence), while the comparator can handle the supertype of T.
内容的提问来源于stack exchange,提问作者fps
相关产品推荐
相关产品推荐

