Java generic parsing (03): the VM executes the generic code, java03
Java generic parsing (03): executing generic code on a VM
The Java virtual machine does not have generic objects. All objects belong to common classes, and even in the early versions of generic implementations, you can compile a program that uses generics into a class file that can be run on the 1.0 virtual machine. This backward compatibility will be discarded later, therefore, if the Generic Code Compiled by Sun's compiler is not run on a VM before Java5.0, this will lead to some actual production problems, for example, to understand how legacy code is connected to a new system, you need to first understand how the VM executes generic code. A mechanism of virtual machines:Erase the type parameter and replace it with a specific type. If no specific type is specified, use Object instead., Such as the Couple <T> class in the previous article. After the virtual machine is erased:[Code01]
public class Couple { private Object wife ; private Object husband ; public Couple(Object wife, Object husband) { this.wife = wife; this.husband = husband; } public void setWife(Object wife) {this. wife = wife;} public void setHusband(Object husband) {this. husband = husband;} public Object getWife() {return wife;} public Object getHusband() {return husband;} }
The type parameter T is of any type, so the Object is replaced by the erased Object. Whether Couple <Employee> or Couple <String> is erased, it becomes the original class Couple class, which is like returning to the general class before the generic type is introduced into Java. So here we focus on
Erased ParametersThis mechanism is explained in detail. How can I replace a type parameter with a type limit? The erasure type parameter mechanism tells us to use a limited type instead. If there are more than one, use the first one. Let's look at a piece of code:
[Code02]
public class Period<T extends Comparable<T> & Serializable> { private T begin; private T end; public Period(T one, T two) { if (one.compareTo(two) > 0) {begin = two;end = one; } else {begin = one;end = two;} } }
After code02 is erased, the original Period type is as follows:
[Code03]
public class Period { private Comparable begin; private Comparable end; public Period(Comparable one, Comparable two) { if (one.compareTo(two) > 0) {begin = two; end = one; } else {begin = one; end = two;} } }
Think about it.
ExtendsComparable <T> & Serializable> is written as Period <T
ExtendsWhat about Serializable & Comparable <T>? Similarly, after erasure, the original type is replaced by the first Serializable. In this way, when the compareTo method is called, the compiler will perform the necessary forced type conversion, so in order to improve the efficiency, put the tag interface (an interface without any method, also called the tagging Interface) at the end. Let's take a look at what happened when the virtual machine executes the expression, such as: [code04]
Couple<Employee> couple = ...; Employee wife = couple.getWife();
After the Object is erased, getWife () returns the Object type, and then inserts the forced type conversion into the virtual opportunity to convert the Object to Employee. Therefore, the virtual machine actually executes the following two-day command: 1. call Couple. getWife () method. 2. convert an Object to the Employee type.
Let's take a look at what happened when the VM executes the generic method. The generic method is as follows:
[Code05]
Public static <T extends Comparable <T> max (T [] arrays) {...} is erased and then: public staticComoparable max (Comparable [] arrays ){...}
However, the erasure of the generic method brings two complicated problems. Check the first instance, one instance: [code06].
public class Period <T extends Comparable<T> & Serializable> { private T begin; private T end; public Period(T one, T two) { if (one.compareTo(two) > 0) {begin = two;end = one; } else {begin = one;end = two;} } public void setBegin(T begin) {this. begin = begin;} public void setEnd(T end) {this. end = end;} public T getBegin() {return begin;} public T getEnd() {return end;} } public class DateInterval extends Period<Date> { public DateInterval(Date one, Date two) { super(one, two); } public void setBegin(Date begin) { super.setBegin(begin); } }
After the DateInterval type is erased, the method in Period becomes:
Public VoidSetBegin (Object begin ){...}
The method in DateInterval is:
Public VoidSetBegin (Date begin ){...}Therefore, DateInterval inherits from Period.
Public
VoidSetBegin (Object begin) {...} and its own existence
Public
VoidSetBegin (Date begin) {...} method. An error occurred during use:
[Code07]
Period<Date> period = new DateInterval(...); period.setBegin(new Date());
Here, because the period reference points to the DateInterval instance, according to the polymorphism, setBegin should call the setBegin method of the DateInterval object, but this erasure causes
Public
VoidSetBegin (Object begin) {...} is called, resulting in a erasure conflict with polymorphism. What should I do? The VM generates a bridge method in the DateInterval class. The call process changes slightly:
[Code08]
public void setBegin(Object begin) { setBegin((Date)begin); }
With the combined bridge method, the call steps for setBegin in code07 are as follows: 1. Call the DateInterval. setBegin (Object) method. 2. Call the DateInterval. setBegin (Object) method to call the DateInterval. setBegin (Date) method. Have you found out? What will it look like when we add the getBegin method in DateInterval? Is there an Object getBegin () method in Peroid, and a Date getBegin () method in DateInterval? These two methods cannot exist at the same time in Java? However, after Java 5, a covariant type is added, which is allowed here. You can see the getBegin method in DateInterval: [code09]
@Override public Date getBegin(){ return super.getBegin(); }
@ Override is used here, which indicates that the Object getBegin () method of the parent class is overwritten, And the return value can be specified as a subclass of the return value type in the parent class. This is the covariant type, this is only allowed after Java 5, and a stricter type (Child type) can be specified after the subclass overwrites the method ).
Summary:1. Remember that there is no generic type in the virtual machine, and there are only common classes. 2. All generic type parameters are replaced by their defined types. If they are not specified, objects are used. 3. To ensure type security, the virtual machine inserts forced type conversion when necessary. 4. Synthesis of the bridge method is used to maintain polymorphism. 5. The covariant type allows subclass to overwrite the method and return a more rigorous type.
Java generic parsing (01): Understanding generics
Java generic parsing (02): wildcard restrictions
Java generic parsing (03): executing generic code on a VM
Java generics solve the array problem, just learning generics, help
Sequential contraction of integer Arrays
Public static int seqSearch (int [] arr, int first, int last, int target ){
For (int I = first; I <last; I ++)
If (arr [I] = target)
Return I;
Return-1;
}
List generics in JAVA
Yes
The above is the get method of ArrayList, which is strongly converted when returned.
If the generic type is not specified, it is of the Object type. If the generic type is specified and the type is incorrect, you do not put the Object.