为何泛型类型参数不支持下界?是否存在特定原因?
super? Great question! Let's unpack why Java doesn't allow declaring a generic type parameter with a lower bound (like <T super Number>) in your method, and why that specific syntax fails to compile.
1. Type Safety is the Core Design Constraint
Java's generics exist primarily to enforce compile-time type safety—catching type mismatches before your code runs. If we allowed <T super Number>, the type parameter T could be any supertype of Number: Number itself, Object, or even an interface like Serializable (if Number implements it).
Imagine your method tried to copy elements from src to dest:
public <T super Number> void copy(T[] dest, T[] src) { System.arraycopy(src, 0, dest, 0, src.length); }
If someone called this with copy(new Number[5], new Object[5]), the src array could contain non-Number objects (like a String). At runtime, storing those elements into a Number[] would throw a ClassCastException—a mistake generics are explicitly designed to prevent at compile time. The compiler can't validate that all elements in src are compatible with T when T has a lower bound, since supertypes can hold arbitrary, incompatible objects.
2. Type Parameters vs. Wildcards: Distinct Roles
Java does support lower bounds—just not on type parameters. Instead, we use wildcards (? super Number) for this scenario. Here's the key distinction:
- A type parameter (
<T>) represents a specific, reusable type you can reference throughout the method (e.g., creating instances ofT, returningT, or assigning toTvariables). - A wildcard (
?) represents an unknown type with a constraint, meant only to restrict what you can do with a parameter (not to be used as a concrete type).
For your copy use case, the correct safe syntax follows the PECS principle (Producer Extends, Consumer Super):
public void copy(List<? super Number> dest, List<? extends Number> src) { for (Number num : src) { dest.add(num); } }
Here, ? extends Number ensures src only produces Number or its subtypes (safe to read from), and ? super Number ensures dest can consume Number or its supertypes (safe to write to). Type parameters don't fit here because we don't need a reusable concrete type—we just need to constrain the parameter types.
3. Ambiguity Breaks Type Inference
When you declare a type parameter with a lower bound, the compiler can't reliably infer a concrete T that satisfies the constraint. For example, if you call <T super Number> copy(...), T could be Number, Object, or any other supertype. This ambiguity makes it impossible for the compiler to validate operations that rely on T being a specific type (like assigning to a T variable or instantiating T).
内容的提问来源于stack exchange,提问作者Darshan

