Generic type
Limits the elements in the collection to a specific type.
Terms
- arraylist<e> --generic type
- ArrayList --Original type
- E --type parameters
- <> -read as "typeof"
- arraylist<integer> --parameterized type
- Integer --Actual type parameter
A few notes:
The parameterized type and the original type are mutually compatible
ArrayList collection1 = new arraylist<integer> ();//pass, no warning
arraylist<integer> collection2 = new ArrayList ();/through, there warning
Parameterized types do not consider inheritance relationships for type parameters
arraylist<string> Collection3 = new arraylist<object> ();//compilation does not pass
arraylist<object> Collection4 = new arraylist<string> ()//compile does not pass
But
ArrayList collection5 = new arraylist<integer> ();
arraylist<string> collection6 = collection5;//compiled by
"?" Wildcard characters
"?" Represents any type, using the "?" Wildcards can refer to various parameterized types, can call methods that are not parameterized (such as the size () method), and cannot invoke methods related to parameterization (such as the Add () method)
Extension of wildcard characters
Limit the upper bounds of the wildcard character
arraylist<? Extends number > collection1= new Arraylist<integer > ();/compile through
arraylist< extends number > collection2= new arraylist<string> ()//compile does not pass
Limit the bottom bounds of wildcard characters
arraylist<? Super integer > Collection3= new Arraylist<number > ()//compile through
arraylist< Super integer > Collection4= New arraylist<string> ()//compile does not pass
Custom generic methods
C + + template functions
Template <class t> t Add (t X, t y) {return
(t) (x+y);
}
The Java generics are basically implemented in the compiler, for the compiler to perform type checking and type judgments, and then generate generic, non-generic bytecode, the implementation of which is "erase" (erasure).
Erase instance
Generics are input types that are used by the Javac compiler to qualify collections, and the compiler compiles a collection with a type description to remove the "type" information.
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 ());
The same class type, that is, byte code consistent
System.out.println (Collection2.getclass (). GetName ());
Class is java.util.ArrayList with 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 reference types can be examples of the actual parameters of a generic method:
public class Generictest {public
static void Main (string[] args) {
swap (new string[]{"111", "222"},0,1);/compile by C3/>//swap (new int[]{1,2},0,1);
Compilation does not pass because int is not a reference type
swap (new integer[]{1,2},0,1);//Compile through
}/
* Swap array A of the first and the J elements/public
static <t > void Swap (T[]a,int i,int j) {
T temp = a[i];
A[i] = a[j];
A[J] = temp;
}
}
However, note that the base type can sometimes be used as an argument because there are automatic boxing and unboxing. Example (compilation passed):
public class Generictest {public
static void Main (string[] args) {
new Generictest (). Testtype ();
int a = Biggerone (3,5);
int and double, taking the intersection of number number
B = Biggerone (3,5.5);
string and int are fetched as Object
C = Biggerone ("1", 2);
}
Returns y public
static <T> t Biggerone (t x,t y) from x,y {return
y;
}
}
At the same time, the example also shows that when the argument is inconsistent, T takes the intersection, that is, the first common parent class. In addition, if the number B = Biggerone (3,5.5) is changed to string c = Biggerone (3,5.5), the error is compiled:
Error: (IN) Java: Incompatible type: Inferred type does not meet the upper bound
Inferred: java.lang.number&java.lang.comparable<? Extends java.lang.number&java.lang.comparable<?>>
Upper Limit: java.lang.string,java.lang.object
But one thing's not clear, I'm in idea one step debugging, found the result is as follows: Generic Debug screenshot-1 do not know why B is a double type (but direct double b receives the return value compiles an error). I don't know if it has anything to do with the IDE, does the IDE show the most accurate type of object in debug?
Type inference for type parameters
The process by which the compiler determines the actual type parameters of a generic method is called type inference.
When a type variable is applied only to one of all parameters and return values in the entire argument list, it is determined by the actual application type at the time the method is invoked. That is, the type of the generic parameter is determined directly based on the parameter type or return value that is passed when the method is invoked. For example:
Swap (new string[3],1,2)-> static <E> void Swap (E[]a,int i,int j)
When a type variable is applied at multiple places in all parameters and return values of the entire argument list, the type of the generic parameter is the type if so many of the actual applied types are corresponding to the same type when the method is invoked. For example:
Add (3,5)-> static <T> t Add (t a,t B)
When a type variable is applied in all parameters and return values of the entire argument list, if you call a method with so many actual application types that correspond to different types, and if there are no return values, then the largest intersection type in multiple arguments is the first public parent class. For example:
Fill (new integer[3],3.5)-> static <T> void Fill (T a[],t v)
This example actually corresponds to the type is number, compile pass, run a problem.
When a type variable is applied at multiple places in all parameters and return values of the entire argument list, the type of the return value is preferred if so many of the actual applied types in the method are called with different types, and the return value is used.
For example:
int x = Add (3,3.5)-> static <T> t Add (t a,t B)
The example above compiles an error, the X type is changed to float and the error is 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)
This example infers that the actual parameter type is object and is compiled through.
Copy (new arraylist<string>,new integer[5])-> static <T> void copy (COLLECTION<T>A,T[]B)
In this example, the type variable is directly determined to be a string type based on the parameterized ArrayList class instance, and the error is compiled.
Custom generic Classes
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 as generic, it can only be called by instance variables and methods (and inline types), not by static variables and static methods. Because static members are shared by the parameterized class, static members should not have class-level type parameters.
Comparison of generic methods and generic classes
Example:
public class a<t> () {
//The member method of the generic class, which is restricted by the t of a after a, public
T Memberfunc () {return
null;
}
Generic methods, where T and and Class A T are different public
static <T> t Genericfunc (t. A) {return
null;
}
public static void Main (string[] args) {
//compilation does not pass
//integer i = a<string> (). Findbyusername ("s");
Compiled via
set<integer> set= a<string> (). Findbyconditions ("s");
}
Here integer i = a<string> (). Findbyusername ("S"); the error is compiled:
Error: (%) Java: Incompatible type: Java.lang.String cannot be converted to Java.lang.Integer
By this example, the t of a generic method is different from the t of Class A.
Generics and reflection
To obtain the actual type parameters of a generic by reflection
Take the generic variable as the parameter of the method, and use the Getgenericparametertypes method of the methods class to obtain an example of the actual type parameter of the generic type:
public class Generictest {public
static void Main (string[] args) throws Exception {
getparamtype ();
}
/* Use reflection to get the actual parameter type of the method parameter
/public static void GetParamType () throws nosuchmethodexception{methods
= GenericTest.class.getMethod ("Applymap", map.class);
Gets the type of the generic parameter of the method
type[] types = Method.getgenericparametertypes ();
System.out.println (Types[0]);
Parameterized type
parameterizedtype ptype = (parameterizedtype) types[0];
Original Type
System.out.println (Ptype.getrawtype ());
Actual type parameter
System.out.println (ptype.getactualtypearguments () [0]);
System.out.println (Ptype.getactualtypearguments () [1]);
}
/* Methods for testing parameter types *
/public static void Applymap (Map<integer,string> Map) {
}
}
Output results:
Java.util.map<java.lang.integer, java.lang.string>
interface Java.util.Map
class Java.lang.Integer
class Java.lang.String