1. Generic Programming
generic programming means that the code you write can be reused by many different types of objects. For example, you do not want to design separate classes for aggregating string and integer objects. (I think this is what I'm saying here.) Create an object that can be of type string and integer. But have the same behavior or attributes)
The code is as follows:
Public class stringtest { private String age; Public String getage () { return age ; } Public void setage (String age) { this. Age = Age ; }}
Public class integertest { private Integer age; Public Integer getage () { return age ; } Public void setage (Integer age) { the age= age ; }}
You can see that all two of the above classes have a Size property and method. Only their attribute types are different. Then we can use the generic type: Example
Public class Generictest<t> { private T size; Public T GetSize () { return size; } Public void setSize (T size) { this. size = size; }}
Then only the following calls are required
Public Static void Main (string[] args) { generictestnew generictest<>(); GenerictestNew generictest<>(); }
So that we can solve the problem of code reuse, right? Can't you read it? No hurry, I just said the benefits of generics, let us slowly understand.
2. Define a simple generic class
The students who have not been exposed to the generics can see that the T in the above example may feel like a crazy face, but T is just a type variable of a class (although you can define a, B, C ..., but we still want to standardize the point of it), then T needs to use angle brackets, when you define more than one type variable. Can look at the following generic class,
Public class Generic<t,u> { private T size; Private U length; ...}
When you pass in generic<integer,string>, you can think of this class as using
Public class Generic { private Integer size; Private String length; ...}
Therefore, generic classes can actually be seen as ordinary factory classes.
3. Generic methods
Here's a simple generic class, let's see how the generic method is written.
Public class Arrayalg { publicstatic <T> t Getmiddle (t ... a) { return A [A.length/2]; }}
As you can see, Arrayalg is a normal class, not a generic class. Description: Generic methods can be defined in normal classes and generic classes.
When we call the Getmiddle method, the angle brackets in front of the method name are placed in the concrete type:
String s = arrayalg.<string>getmiddle ("John", "Q", "Min");
Does it look like it's awkward? In fact, you can omit the <String> type parameter, the compiler will use the string[] array and the generic t[] to infer that it must be a String, this should be their private bilibili rules. Become:
String s = arrayalg.getmiddle ("John", "Q", "Min");
Some small partners may think, jiangzi words, I can be blind to pass parameters in? Cases:
Double middle2 = Arrayalg.getmiddle (3.14,0);
In fact, when you write this, the compiler has already prompted the error, because the second parameter compiler will default to the integer type. There are two ways to resolve this:
1. Change the double to number type because the number type is the parent class of double and Integer.
2. Change the code yourself, who makes you blind.
4. Qualification of type variables
Sometimes a class or method needs to constrain a type variable , and if a generic method needs to use the CompareTo method to the comparable interface, then we need to limit the arguments that are passed in to implement the comparable interface, for example:
Public Static extends Comparable> T Minmax (t[] a) {compareTo ...}
The parameter a passed in must implement the comparable interface. If the parameters required to implement comparable and serializable two interfaces, then
Public Static extends Comparable&serializable> pair<t> Minmax (t[] a) { compareTo ... }
Ding dong! So the passed in parameters need to inherit a class how to write? is actually the same. The passed in parameters need to inherit a class and implement an interface that is controlled using the extends keyword. Cause: The reason for choosing the keyword extends is that it is closer to the concept of a subclass, and the Java designer is not going to add a new keyword to the language
5. Generic code and virtual machines
5.1 Type Erase
Java generics are valid in the compiler and are deleted at run time, i.e. all generic parameter types are erased after compilation
For example:
Public class Genericclass<t> { private T first; Public T GetFirst () { return first ; } ...}
After erasing a type
Public class Genericclass { private Object first; Public Object GetFirst () { return first ; } ...}
As you can see, the type erased Gengericclass and no reference generics are the same. Also, when you use genericclass<string>, it becomes the original genericclass type.
But when we use a qualified type variable, the type erase will use the qualified type. Cases:
Public class extends Comparable> { private T first; ...}
You can see that the passed-in parameters need to be implemented comparable interface, then the type erase is as follows:
Public class genericclass{ private comparable first; ...}
problem: When you define the parameters you need to implement the comparable and Serializable interfaces, that is Genericclass<t extends comparable&serializable> , what happens when the type is erased?
Public class genericclass{ private comparable first; ...}
The virtual opportunity converts the first implemented interface (here comparable) to the erased object type. Of course, if you write genericclass<t extends serializable&comparable> , then the erased type is Serializable.
5.2 Translating generic expressions
When a program invokes a generic method, the compiler inserts a forced type conversion if the return type is erased. For example list collection source code:
Public Interface extends collection<e> { ... E get (int index); ...}
When a type variable is not used, the value taken is object, and when a variable of type string is defined, the compiler inserts a forced type conversion:
New ArrayList ();
List1.add ("1"); List1.get (//ObjectListnew arraylist<> ();
List2.add ("1"); List2.get (//String
However, when in a virtual machine, List2.get (0) is translated into two virtual machine commands at the time of the call:
1. Get method calls to the original method list collection
2. Convert the returned object to a forced type into string
5.3 Translating generic methods
What happens to a generic method when the Genericsubclass class inherits the generic class?
Public class Generic<t> { private T size; Public T GetSize () { return size; }
...}
Public class extends Generic<integer> { @Override public Integer getsize () { return Super. GetSize (); }}
is @override really overriding the parent class method at this point? By the time the generic is typed, the return type of the GetSize method becomes object:
Public return size; }
The return type of Genericsubclass's GetSize method is integer:
Public return Super. GetSize (); }
This is not a method of overriding the parent class, because the method is not the same, resulting in genericsubclass having two getsize methods in the virtual machine:
Public Integer GetSize () { ... } Public Object GetSize () { ... }
The cause is that type erasure conflicts with polymorphism. To resolve this problem, the virtual machine automatically generates a bridge method in Genericsubclass:
Public return (Integer) Super. GetSize (); }
Finally, the virtual machine calls its own generated bridge method to resolve this conflict.
If there are shortcomings, please Daniel in the following message that thanks♪ (・ω・) Dentetsu