Generics of java basic study notes
- 2020-05-05 11:13:16
- OfStack
generic
Qualifies an element in a collection to a specific type.
The term
ArrayList < E > -- generic type ArrayList -- primitive type E -- type parameter < > - pronounced "typeof ArrayList" < Integer > -- parameterized type Integer -- actual type parameterA few notes:
The parameterized type and the primitive type are mutually compatible with
ArrayList collection1 = new ArrayList<Integer>();// through , There is no warning
ArrayList<Integer> collection2 = new ArrayList();// through , There are warning
Parameterized types do not consider the inheritance of type parameters
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
But
ArrayList collection5 = new ArrayList<Integer>();
ArrayList<String> collection6 = collection5;// Compiled by
& # 63; "" The wildcard character
"The & # 63;" For any type, use "?" Wildcards can refer to various parameterized types, can call methods that are not parameterized (such as size()), and cannot call methods that are parameterized (such as add()),
extension of wildcard
Qualifies the upper edge of a wildcard,
ArrayList<? extends Number > collection1= new ArrayList<Integer >();// Compiled by
ArrayList<? extends Number > collection2= new ArrayList<String>();// Compile not pass
Qualifies the lower boundary of the wildcard,
ArrayList<? super Integer > collection3= new ArrayList<Number >();// Compiled by
ArrayList<? super Integer > collection4= new ArrayList<String>();// Compile not pass
custom generic method
C++ template function
template <class T> T add(T x, T y){
return (T)(x+y);
}
Generics of java, on the other hand, are implemented almost entirely in the compiler, which performs type checking and type determination, and then generates plain, non-generic bytecode, an implementation technique known as "erasing" (erasure).
"erase" instance
Generics are provided to the javac compiler to qualify the input type of a collection, which removes the "type" information when compiling a collection with a type description.
public class GenericTest {
public static void main(String[] args) {
new GenericTest().testType();
}
public void testType(){
ArrayList<Integer> collection1 = new ArrayList<Integer>();
ArrayList<String> collection2= new ArrayList<String>();
System.out.println(collection1.getClass()==collection2.getClass());
// both class Type the same , That is, the bytecode is consistent
System.out.println(collection2.getClass().getName());
//class Are all java.util.ArrayList, There is no actual type parameter information
}
}
Output
true
java.util.ArrayList
Use reflection to skip the compiler and add other types of data to a generic collection.
Only the reference type can be used as an example of the actual parameter of a generic method:
public class GenericTest {
public static void main(String[] args) {
swap(new String[]{"111","222"},0,1);// Compiled by
//swap(new int[]{1,2},0,1);
// Compile not pass , because int Not a reference type
swap(new Integer[]{1,2},0,1);// Compiled by
}
/* Exchange of array a The first i And the first j An element */
public static <T> void swap(T[]a,int i,int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
Note, however, that the base type can sometimes serve as an argument because of autoboxing and unboxing. Example (compiled) :
public class GenericTest {
public static void main(String[] args) {
new GenericTest().testType();
int a = biggerOne(3,5);
//int and double, Take delivery for Number
Number b = biggerOne(3,5.5);
//String and int Take delivery for Object
Object c = biggerOne("1",2);
}
// from x,y In return y
public static <T> T biggerOne(T x,T y){
return y;
}
}
The example also shows that when arguments are inconsistent, T takes the intersection, the first common parent. In addition, if Number b = biggerOne(3,5.5); String c = biggerOne(3,5.5); Then compile error report :
Error:(17, 29) java: incompatible type: inferred type does not meet upper limit
conclude java. lang. Number & java. lang. Comparable<
? extends java.lang.Number&java.lang.Comparable
<
?
>
>
ceiling: java. lang. String, java. lang. Object
However, there is one thing that is not clear, I step in IDEA debugging, and found the following figure: generic debugging screenshot -1 do not know why b is Double type (but directly Double b received the return value will compile the error). I don't know if it has anything to do with IDE, does IDE display the most precise type of this object when debug?
Type inference for type parameters
The process by which the compiler determines the actual type parameter of a generic method is called type inference.
When a type variable is applied to only one of the parameters and return values in the entire parameter list, it is determined based on the actual application type at the time the method is called. That is, the type of a generic parameter is determined directly based on the parameter type or return value passed when the method is called. For example:
swap(new String[3],1,2) -> static <E> void swap(E[]a,int i,int j)
When a type variable is applied to more than one of all the arguments and return values in the entire parameter list, the type of a generic parameter is the same if the actual application types in so many places correspond to the same type when the method is called. For example:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
0
When a type variable is applied to * in all parameters and return values in the entire parameter list, if the actual application types in so many places correspond to different types when the method is called, and there is no return value, the maximum intersection type in the multiple parameters is taken, that is, the first common parent class. For example:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
1
The actual type of this example is Number.
When a type variable is applied in multiple places in all parameters and return values of the entire parameter list,
of the return value is preferred if the actual application type in so many places corresponds to a different type when the method is called and a return value is used
For example:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
2
The above example reported an error,x type changed to float also reported an error, changed to Number success.
Type inference for parameter types is transitive
Example:
copy(new Integer[5],new String[5]) - > static < T > void copy(T []a,T []b)
The example concludes that the actual parameter type is Object
copy(new ArrayList < String > ,new Integer[5]) - > static < T > void copy(Collection < T > a,T[]b)
This example directly determines the type variable as String type according to the parameterized ArrayList class instance, and compiles and reports an error.
Custom generic class
Example
public class GenericDao<T>{
public void add(T x){
}
public T findById(int id){
return null;
}
public void delete(T obj){
}
public void delete(int id){
}
public void update(T obj){
}
public T findByUserName(String name){
return null;
}
public <T> Set<T> findByConditions(String where){
return null;
}
}
Note: when a variable is declared generic, it can only be called by instance variables and methods (as well as embedded types), not by static variables and static methods. Because static members are Shared by parameterized classes, static members should not have class-level type parameters.
Comparison of generic methods and generic classes
Example:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
4
Here Integer i = A< String > (a). findByUserName (" s "); Will compile error:
Error: (35, 61) java: incompatible types: java. lang. String unable to convert java. The lang. Integer
From this example, the T of a generic method is different from the T of class A.
generics and reflection
The actual type parameter
of the generic is obtained by reflectionUsing the getGenericParameterTypes method of the Method class to get an example of the actual type parameter of the generic:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
5
Output:
ArrayList<String> collection3 = new ArrayList<Object>();// Compile not pass
ArrayList<Object> collection4 = new ArrayList<String>();// Compile not pass
6