First, Introduction
Review Javac The compilation process of the solution syntax sugar when you see the generic erase in the example, the information on the Internet is mostly more specific, in this make their own some detailed and understandable summary.
Ii. Introduction of generic type
Generics are a new feature of JDK 1.5, a paradigm used by compilers, a kind of syntax sugar that guarantees type safety. Note: In inheritance, the subclass generic number must be not less than the parent generic number "
For ease of understanding, I divide generics into generic and wildcard generics
Iii. Generic classification
1. General generic type
Is that generics are not set, and generics are represented as a class.
when declaring: class test<t>{...}
When used: test<integer> Test = new test<integer> ();
As unbounded generics, it is in fact the constraints around the generic type must be consistent.
2, the general distribution of the generic
The universal generic includes two kinds of, unbounded pass-through and bounded pass-through distribution.
"Unbounded wildcard character"
<?> Wildcard -- indicates that all types can match it
"Bounded wildcard character"
extends (upper bound) wildcard --declares the upper bounds of the type, indicating that the parameterized type is either the specified type or a subclass of this type;
Super (Nether) wildcard -- Declares the nether of a type, indicating that the parameterized type may be the type specified, or the parent type of this type, until object. After type erase (extends example below)
// bounded generic type syntax-inherits from a parent class <t extends classa>// Bounded generic type syntax-Implements an interface <t extends interfaceb> // bounded generic type syntax-multiple bounds <t extends ClassA & Interfaceb & interfacec >// example <n extends number> // n identifies a generic type whose type can only be a subclass of the number abstract class <t extends number & Comparable & map> // t identifies a generic type, Its type can only be a subclass of the person type, and implements the comparable and map interfaces
"Note: In multiple boundaries, only the first can be allowed for the class, and subsequent must be the interface"
Iv. differences between List<t> and List<?> and list<object>
class declaration is list<t>, at which point T can be any letter, referring to generic generics.
For example: class test<t>{...}
Use List<?> when instantiating, at this time? Can be any class, that can only be stored in such an object, or write ' <?> ', the representative can be stored in any class object, belong to a wildcard generic.
For example: list<? > listofstring = new arraylist<string>;
But note that list<?> is not the same as list<object>, which is a wildcard of all generics, that is, all generic references can be matched to him (to the right of the instantiation), list<object> List = new arraylist< Object> (); , instantiating the generic on the left as the "answer range", instantiating the generic on the right to "answer" is only one class. For example:
New // Compile Error: Wildcard is "answer range" cannot appear on the right side of the instantiation as "answer" New // string with? Match Success extendsnewextends// Compile error: Bounded generics are also "answer ranges" and cannot appear on the right side of the instantiation extends New // The "answer" on the right matches the "answer range" on the left.
V. Generic Erase
Origin : Java did not have generics at first, and later 1.5 was added to generics, in order to be forward compatible (the older JVM could interpret the new version of the. class file) so it took the pseudo-generic-"generic erase" and kept it.
principle : Generic information exists only in the code compilation phase, before entering the JVM, the information associated with the generic is erased, erased to the original type (minus <t>, and the T inside the method is erased to object) such as Generic<t > will be erased into generic. It is also important to note that there are different ways to erase different wildcard characters:
Formula:"incoming: Remove bounds; return: Upper Bounds"
When a generic is passed as an incoming parameter to a method, it is replaced with the lower bound of a wildcard generic , such as the Add method
When the generic is the return parameter of the method, it is replaced with the upper bound of the wildcard generic , such as the Get method
list<?extendsInteger> List1 =NewArraylist<integer>(); List1.add (NULL);//in this case, the incoming < extends Integer> Nether ———— No, so only null, otherwise errorInteger integer1 = list1.get (0);// //return to fetch < at this time; extends integer> upper bound ———— IntegerList<?SuperInteger> List2 =NewArraylist<integer>(); List2.add (111);//at this point the incoming fetch <? Super Integer> Nether —————— IntegerInteger integer2 = (integer) list2.get (0);// //at this point return to take <? Super Integer> Upper bound ———— Object
So similarly, when the generic is <?>, the removal bounds is null and the upper bound is object.
So come to the conclusion that because of the erase limitations of the add and get methods, use the generic generics as little as possible
What are the pitfalls of generic erasure, and what are the workarounds :
1. If you do not add generic inheritance, the erase will become the original type, so you can add non-generic type. list<integer> List = new arraylist<integer>(); List.add ("aha");
And can accomplish reference passing between different generics. list<string> List = new arraylist<integer> ();
How do you solve both of these situations?
--TheJava compiler is to check the code for the type of generic, if the above two cases will be in the compile time error, check the pass, and then type Erase, and then compile.
Note: First check that the instantiation of the left and right generics matches, and then check the added elements on the left-hand generics of the instantiation (so, just write the generic and not write is a meaning) " For example:
New // The generic is checked at this time by string New Arraylist<string> (); // generics are not checked at this time
2, erase after the generic information is gone, get the time again strong turn?
-- Generic compensation : Under the guarantee of generic checks, the objects are stored in a generic type, and the type of the element object (GetClass () method) that is used to get the outgoing element is strongly turned during compilation.
3, the subclass inherits the generic method, then overrides it and changes the generic to the real type, but after erasing the original parent class's generic method becomes the object method and becomes two different methods, so this method is not an inheritance override, but a subclass of overloading. As shown in the following code:
class node<t> { public void SetData (T data {System.out.println ( "Node.setdata" class mynode<t> extends Node<integer> public void SetData (Integer data) {System.out.println (" Mynod E.setdata: "+data); } }
New Mynode<integer>(); N.setdata (// If the object method is erased, the method of the parent class is executed, and the "Node.setdata" is printed out
Operation Result: mynode.setdata:1213
Can you see how the subclass is executed? The implementation of polymorphic is completed. How is this solved?
-- Bridge method : As the name implies, because the parameter list of the methods in the subclass after erasing is different from the parent parameter list, it cannot be overridden, so when the compiler is compiled, After erasing, insert some methods into the subclass to reload the object method after all the generic erase in the parent class, and call the corresponding subclass method inside the method to re-form the polymorphism between the parent and child, which is called the bridge method. (The following is what the compiler erased after compiling)
class Node { public void SetData (Object data) { System.out.println ( "Node.setdata" class mynode extends Node { // compiler-generated bridge method public void SetData (Object data) {SetData ((Integer) data); public void SetData (Integer data) {System.out.println (" mynode.setdata: "+data); } }
Generic differences in Java and generic erase explanations