Directory
?edit
1. Generics
1.1 The Object class leads to the concept of generics
2. Generic syntax
2.1 Generic writing code
3. Generic mechanism
3.1 Erase Mechanism
4. The upper bound of generics
4.1 Syntax of generic upper bounds
4.2 The use of generic upper bounds
5. Generic methods
5.1 Generic method syntax
5.2 Use of generic methods
1. Generic
In general classes and methods, only specific codes can be used to implement operations on the same type of data. For example, the same type is stored in an array, and this storage method is too rigid. Therefore, JDK1.5 introduces a new syntax: generics. Generally speaking, generics are multiple data types (flooding). From the code point of view, it is to realize the storage between different types, so We use generics when we want to store various kinds of data.
1.1Object class leads to generic concept
Before generics, we learned from the Object class that the parent class of all classes is the Object class, so we can set an array as the Object type, so that various elements can be stored in the array. So we can write code like this:
class MyArray { //Object type array Object[] arr = new Object[3]; public void show() { //Initialize three different types of data respectively arr[0] = 1; arr[1] = 1.2; arr[2] = "abc"; //Loop through the arr array for (int i = 0; i < arr. length; i ++ ) { System.out.println(arr[i]); } } } public class Test { public static void main(String[] args) { MyArray myArray = new MyArray(); myArray. show(); } }
Output after running:
The above code works well because we directly initialize the elements in the Object class. When we use the get and set methods to implement, we will find the difference.
class MyArray { //Object type array public Object[] arr = new Object[3]; //Provide the get method public Object getPos(int pos) { return this.arr[pos]; } //Provide the set method public void setArr(int pos, Object value) { this.arr[pos] = value; } } public class Test { public static void main(String[] args) { MyArray myArray = new MyArray(); // Set three different types of elements respectively myArray. setArr(0,1); myArray.setArr(1,1.2); myArray.setArr(2,"abc"); //Output three different types of elements System.out.println(myArray.getPos(0)); System.out.println(myArray.getPos(1)); //When outputting the character type, an error is reported System.out.println(myArray.getPos(3)); } }
Output after running:
We found , an exception occurs when I add a string to the array. Therefore, when Object stores different types
Errors still occur. Therefore, we can think that since I am not allowed to store different types of data, then I just store the same type of data, and then we can use generics. It can store different types of data in different objects, but the type of each element in different objects is the same.
2. Generic syntax
(1) Grammar 1
//Generic class syntax format class generic class name <type parameter list> { //content } // There can be multiple formal parameters in a generic class class ClassName<T,S,B,U> { //content }
In the above code, we can see that there is one more <> between the generic class and the ordinary class, and the rest is not much different. Note that multiple parameters can be written in <>.
(2) Syntax 2
//generic class inheritance class or generic class class generic class name <type parameter list> extends class name { } // Generic class inherits generic class class ClassName1<T,S,B,U> extends ClassName2<T> { }
The above code indicates that a generic class can inherit a common class or a generic class.
2.1 Generic writing code
Therefore, we can write a generic code like this:
class MyArray<T> { //Create a generic array T[] arr= (T[])new Object[3]; //get method public T getPos (int pos) { return this.arr[pos]; } //set method public void setArr (int pos,T value) { this.arr[pos] = value; } } public class Test { public static void main(String[] args) { //myArray1 object sets int type data MyArray<Integer> myArray1 = new MyArray<>(); myArray1.setArr(0,1); myArray1.setArr(1,2); myArray1.setArr(2,3); //myArray2 object sets String type data MyArray<String> myArray2 = new MyArray<>(); myArray2.setArr(0,"a"); myArray2.setArr(1,"b"); myArray2.setArr(2,"c"); // Output each subscript element through the get method System.out.print(myArray1.getPos(0) + " "); System.out.print(myArray1.getPos(1) + " "); System.out.print(myArray1.getPos(2) + " "); System.out.print(myArray2.getPos(0) + " "); System.out.print(myArray2.getPos(1) + " "); System.out.print(myArray2.getPos(2)); } }
Output after running:
The above code is a manifestation of generics. If we want to set what type of data, we can set what type of wrapper class in <>. I believe that the get and set methods in the above code are not difficult for everyone to understand, but many friends may not be clear about some problems when they see this kind of code for the first time, so I will explain it:
after the class name represents a placeholder, indicating that the current class is a generic class. The content in <> can be filled in arbitrarily, you can enter E, K, N and so on. Note that you should fill in the meaning of the name, such as T for type and N for number. - T[] arr = new T[3]; is not feasible, because generics cannot directly new an array, but we can force type conversion such as T[] arr = (T[]) new Object[];.
- When instantiating a generic class, <> can only be a reference type and not a basic type. Therefore, we usually fill in the wrapper class, and the type of the value in the object must be consistent.
- When instantiating a generic class object, the content in the preceding <> must not be omitted, and the content in the following <> can be omitted. Such as: Array
array = new Array<> ();.
3. Generic mechanism
Generics is a runtime mechanism, it will point out some errors to us at compile time, and it will also help us to perform mandatory type conversion when getting elements.
(1) Point out errors when compiling
public static void main(String[] args) { MyArray<int> myArray = new MyArray<>(); }
Error reporting:
The above error means that the <> content type in the generic class cannot be defined as int. As we know above, the generic type <> must be a reference type, so int cannot be used as an internal parameter of <>. Another example is the following code:
public static void main(String[] args) { MyArray<Integer> myArray = new MyArray<>(); myArray.setArr(0,"abc"); }
Error reporting:
The above code , we passed a String type of data when passing parameters to the set method, which did not conform to the properties of the object myArray. Therefore, an error occurs.
(2) Help with type conversion
class MyArray<T> { //Create a generic array public Object[] arr = new Object[3]; //get method public T getPos (int pos) { return (T)arr[pos]; } //set method public void setArr (int pos,T value) { arr[pos] = value; } } public class Test { public static void main(String[] args) { //Integer generic class MyArray<Integer> myArray = new MyArray<>(); //Automatically help us with type conversion myArray.setArr(0,23); //String generic class MyArray<String> myArray1 = new MyArray<>(); //Automatically help us with type conversion myArray1.setArr(0,"abc"); } }
In the above code, the second parameter value of the formal parameter list of the set method is the generic T type, but it is in the main method. When I passed parameters to the setArr method, I directly passed an integer and a string. The compiler didn’t report an error, that’s because the generic type automatically helped us perform the mandatory type conversion, that is, the T type was converted into an integer type and a string type respectively.
3.1 Erasure Mechanism
Through the above explanations, we know that generics will display errors when we compile, which will help us to force type conversion. Shows that generics are a compile-time mechanism. So what will our generics look like after running? In fact, our generic type will be erased as Object type after compilation.
class MyArray<T> { //Create a generic array T[] arr= (T[])new Object[3]; //get method public T getPos (int pos) { return this.arr[pos]; } //set method public void setArr (int pos,T value) { this.arr[pos] = value; } } public class Test { public static void main(String[] args) { //Instance an object whose generic type is Integer class MyArray<Integer> myArray = new MyArray<>(); myArray. setArr(0,1); myArray. setArr(1,2); //Instance an object whose generic type is String class MyArray<String> myArray1 = new MyArray<>(); myArray1.setArr(0,"abc"); myArray1.setArr(1,"def"); } }
After debugging:
We can find that when we create an array, it is T[] arr= (T[])new Object[3];, but the compiler automatically programs the Object type for us in the background. Therefore, we can know that the compiler will erase the generic type and convert it to the Object type for us after running.
So, we can create a generic array like this:
class MyArray<T> { //Create a generic array public Object[] arr = new Object[3]; //get method public T getPos (int pos) { return (T)arr[pos]; } //set method public void setArr (int pos,T value) { arr[pos] = value; } }
The above code initializes the array is an authentic initialization, and the original T[] arr = (T[]) new T[3]; is not very authentic, but it can also achieve the effect.
4. The upper bound of generics
There is a program that requires finding the maximum value of an array through generics, so there is the following code:
class MaxArray<T> { public void findMax(T[] arr) { T max = arr[0]; for (int i = 0; i < arr. length; i ++ ) { if (max > arr[i]) { max = arr[i]; } } System.out.println(max); } } public class Test { public static void main(String[] args) { MaxArray<Integer> maxArray =new MaxArray<>(); Integer[] integers = {1,3,4,5,10,8,9,5,20}; maxArray. findMax(integers); } }
Error reporting after running:
The reason for the error in the above code is the judgment in if. When judging between basic types, arithmetic symbols can be used. When judging between basic types and reference types, we have to use the Comparable method to judge. However, we found that the above-mentioned generic type does not use the Comparable interface, so we can make the generic type inherit this interface to realize the operation, so such an operation represents the concept of the upper bound of the generic type.
4.1 Syntax of upper bounds of generics
class generic class <parameter list extems type bounds> { //content }
The above code is the creation of a parameter type inheriting a type boundary in a generic class, an example:
class Array<T extends Number> { //content }
Only subtypes of Number are accepted as type arguments of T , so we can only use with respect to subtypes of Number, such as Integer. The String type cannot. like:
class Num<T extends Number> { //All three of the following will do Num<Integer> num1 = new Num<>(); Num<Byte> num2 = new Num<>(); Num<Double> num3 = new Num<>(); // will report an error Num<String> num4 = new Num<>(); }
Error reporting:
The jdk-8 help manual describes the following classes as Number subclasses.
4.2 Use of generic upper bound
It is still the code in 4.1. Since we cannot use < to compare a basic type and a reference type, then we make the T type inherit the Comparable interface.
class MaxArray<T extends Comparable<T>> { public void findMax(T[] arr) { T max = arr[0]; for (int i = 0; i < arr. length; i ++ ) { //Use the compareTo method in the Comparable interface if (max. compareTo(arr[i]) < 0) { max = arr[i]; } } System.out.println(max); } } public class Test { public static void main(String[] args) { MaxArray<Integer> maxArray =new MaxArray<>(); Integer[] integers = {1,3,4,5,10,8,9,5,20}; maxArray. findMax(integers); } }
Output after running:
In the above code, the T type in the generic class inherits the Comparable interface, so the compareTo method in the Comparable interface can be used in the if judgment. The value returned by this method is less than 0 means that the former is smaller than the latter, the return value equal to 0 means that the former is equal to the latter, and the return value greater than 0 means that the former is greater than the latter.
5. Generic method
We have learned the use of generic classes above, so generics also have methods. We can turn an ordinary method into a generic method to use, so what is the specific use of the generic method? Let me explain below:
5.1 Generic method syntax
The grammatical format of a generic method is: Method Qualification Modifier
Example:
public <T> T maxNumber(T[] arr) { //content }
5.2 Use of generic methods
Find the largest number in an array:
class Array { public <T extends Comparable<T>> T maxNum(T[] num){ T max = num[0]; for (int i = 0; i < num. length; i ++ ) { if (max. compareTo(num[i]) < 0) { max = num[i]; } } return max; } } public class Test { public static void main(String[] args) { Array array = new Array(); Integer[] arr = {1,23,4,5,6,7}; Integer max=array.<Integer>maxNum(arr); System.out.println(max); } }
Output after running:
The above code shows the use of generic methods. We can see that the syntax of generic methods is relatively abstract, which is the difficulty of generic methods.
This is the end of this blog, thank you for reading.
Next Preview: ArrayList and Sequence List