In general, the usage is no different from the usage, but there is one situation that requires special use <?> Instead of the native type (because unspecified wildcard types are captured and converted to the exact type ).
For example:
Holder <T> Holder (T val) {value = set (T val) {value = T get () {<T> f1 (Holder <T> = f2 (Holder <?> = Holder <Integer> (1 = Object (); f2 (rawBasic); Holder <?> Wildcarded = Holder <Double> (1.0
Capture conversions allow us to bypass the limits of the compiler when processing wildcards. When f2 () calls f1 (), it knows that this is safe because its own holder parameter must be Holder for some unknown V <V>. At the same time, the type parameter T is introduced into the method signature and is not bound to any other type parameter. It can also represent any unknown type. Therefore, the Holder of some unknown T may also be the Box of some unknown V.
The type parameters in f1 () are exact and there are no wildcards or boundaries. In f2 (), the Holder parameter is an unbounded wildcard, so it looks unknown. However, in f2 (), f1 () is called, and the parameter type is captured when f2 () is called. Therefore, it can ().
: T cannot be returned from f2 () Because T is unknown for f2.
Generally, APIs with Wildcards are simpler than APIs with generic methods. Increasing type names in more complex method declarations reduces the readability of declarations. Because the name can always be restored through proprietary capture and conversion as needed, this method can keep the API clean without deleting useful information.