1. Defining generic methods
(1) If you define a generic (class, interface), then Java specifies that you cannot use generic type parameters in all static methods, static blocks, and so on. For example:
public class a<t> {public static < Span class= "Hljs-keyword" >void func (T t) {//error, compilation does not pass}}
(2) How to use generics in static content (static methods), the more general problem is, if the class (or interface) is not defined as generics, but you want to apply generics in some of these methods (such as accepting a generic parameter, etc.), how to solve it?
- Defining a generic method is like defining a generic class or interface, and you need to specify who is the generic parameter in my scope when defining the class name (or interface name). For example: In the scope of
public class A<T> { ... }
Class A, T is a generic type parameter.
- Defines a generic method whose format is: modifier < type parameter list > return type method name (formal parameter list) {method body}. For example:
public static <T, S> int func(List<T> list, Map<Integer, S> map) { ... }
where T and s are generic type parameters.
- The definition of a generic method differs from the definition of a common method in that it is necessary to add a declaration of a generic type parameter between the modifier and the return type, indicating who is the generic type parameter in the scope of the method;
- Neither the generic definition of a common class/interface nor the generic definition of a method can escape two major elements:
- which are generic type parameters;
- Where these type parameters are used.
(3) Scope of type parameters
class A<T> { ... }
The scope of T is the whole A;
public <T> func(...) { ... }
The scope of T is the method func;
Type parameters also have scope coverage issues, and you can continue to define generic methods in a generic template class/interface, for example:
Class a<t> {A is already a generic class whose type parameter is TPublicStatic <T>void Func(T T) {//in which a generic method is defined, and the type parameter of the method is also t}} //when the above two types of parameters conflict, in the method, the t of the method overrides the t of the class, that is, the scope of the normal variable, internally covered outside, the outside of the same name variable is not visible. //unless it is a special requirement, be sure to separate the local type parameter from the external type parameter to avoid unnecessary errors, so it is generally correct to define this way: class a<t> { Public static <S> void func (s s) {}}
(4) The type parameter of a generic method can specify an upper bound, and the type upper limit must be defined at the place where the type parameter is declared, and the upper limit cannot be defined in the method parameter. Specifies that the upper limit can only specify the type argument within the specified range, beyond which the error will be compiled directly.
<T extends X> void func(List<T> list){ ... }
That's right
<T extends X> void func(T t){ ... }
That's right
<T> void func(List<T extends X> list){ ... }
, compilation error
2. Generic invocation
(1) explicitly specify the type parameter of the method, the type parameter is written in angle brackets and placed before the method name. For example object.<String> func(...)
, if you explicitly specify that the type parameter of a generic method is string, then all occurrences of the type parameter T will be replaced with a string type.
(2) implicitly automatically infer that no generic parameters are specified, and the compiler automatically infers the type parameters based on the type of argument passed in. For example: <T> void func(T t){ ... }
implicit invocation object.func("name")
, based on "name"
the type of string inferred type parameter T is of type string
(3) To avoid ambiguity, for example: <T> void func(T t1, T t2){ ... }
If this object.func("name", 15);
is called if the compiler will not error, but there will still be a great hidden trouble, T should be a string or integer existence ambiguity;
(4) Some ambiguous Java is directly as a compilation error, that is, all and generic parameters related ambiguity, for example: <T> void func(List<T> l1, List<T> l2){...}
If this is called, there object.func(new List<String>(), new List<Integer>());
will be ambiguous, the compiler can not know whether T should be string or integer, this ambiguity will directly error, Compilation cannot be passed. That is, in a generic method, if the type parameter is just the type argument of the generic parameter, then the type argument must not be ambiguous, otherwise the direct compilation error.
3. Generic method/Type wildcard
(1) You will find that all the problems that can be solved with the type wildcard (?) can be solved with generic methods, and the generic method can be solved better.
- Type wildcard characters:
void func(List<? extends A> list);
- Can be perfectly solved with a generic approach:
<T extends A> void func(List<T> list);
(2) Two methods can achieve the same effect, "?" can represent any type within a range, and T can also pass in any type argument in the range, and the generic method is further, "?" Generic objects are read-only, and generic objects in generic methods are modifiable, that is, the List<T> list
list in is modifiable.
(3) The most obvious difference between the two
- “?” Generic objects are read-only and cannot be modified because the "?" The type is indeterminate and can represent any type within the range;
- The generic Parameter object in a generic method is modifiable because the type parameter T is deterministic (determined when the method is called), because T can be specified with any type in the range;
(3) Applicable scenarios
- Generally read-only use the "?", to modify the generic method. For example:
public <T> void func(List<T> list, T t) { list.add(t);}
- A generic method should be used when there is a type dependency between multiple parameters and return values, otherwise it should be a wildcard "?". Specifically, if the return value of a method, the type of some arguments depends on the type of another parameter, the generic method should be used, because the dependent type, if it is an indeterminate "?", cannot be relied upon by other elements. For example,
<T> void func(List<? extends T> list, T t);
the first parameter depends on the type of the second argument (the type parameter of the first argument list must be the type of the second argument or its subclass).
<T, E extends T> void func(List<T> l1, List<E> l2);
Here e only occurs once in the formal parameter (the Type argument declaration does not count), and no other thing (method parameter, return value) depends on it, then you can make the E Statute "?". Statute results<T> void func(List<T> l1, List<? extends T> l2);
- Typical application, Container assignment method (Java API):
public static <T> void Collections.copy(List<T> dest, List<? extends T> src) { ... }
from src Copy to dest, then dest preferably SRC type or its parent class, because this is type compatible, and SRC is just read, no need to modify, so use "?" You can also force you to avoid making unnecessary modifications to the SRC to increase security.
"Go" Java generic method