Background: We all know that generics essentially provide "type parameters" of types. They are also called parameterized types (parameterized types) or parametric polymorphism (parametric polymorphism). . In fact, the idea of generics was not first introduced in Java. Templates in C are an example of using generics.
(Recommended video: java video tutorial)
GJ (Generic Java) is An extension to the Java language, a Java language with parameterized types. Programs written in GJ look basically the same as ordinary Java programs, except that they have more parameterized types and fewer type conversions. In fact, these GJ programs are first converted into ordinary Java programs without generics and then processed. The compiler automatically completes the translation from Generic Java to ordinary Java.
We all know that the compiler will perform generic erasure. The compiler can When compiling the source program (Java code with generics), use generic type information to ensure type safety, verify a large number of type safety constraints that would not be verified without generics, and at the same time, in the generated bytecode , clear these type information. Let’s verify it first:
public static void main(String[] args) { ArrayList<Integer> ints = new ArrayList<Integer>(); ints.add(1); ints.add(2); ints.add(3); ArrayList<String> sts = new ArrayList<String>(); sts.add("a"); sts.add("b"); sts.add("c"); System.out.println(ints.getClass() == sts.getClass()); }
The result printed above is true because
According to understanding, the original value cannot be retrieved after generic erasure The types are all in the form of Object. Is this really the case?
Look at the following code:
import java.lang.reflect.ParameterizedType;import java.util.ArrayList;import java.util.List;public class ClassTest { public static void main(String[] args) throws Exception { ParameterizedType type = (ParameterizedType) Bar.class.getGenericSuperclass(); System.out.println(type.getActualTypeArguments()[0]); ParameterizedType fieldType = (ParameterizedType) Foo.class.getField("children").getGenericType(); System.out.println(fieldType.getActualTypeArguments()[0]); ParameterizedType paramType = (ParameterizedType) Foo.class.getMethod("foo", List.class) .getGenericParameterTypes()[0]; System.out.println(paramType.getActualTypeArguments()[0]); System.out.println(Foo.class.getTypeParameters()[0] .getBounds()[0]); } class Foo<E extends CharSequence> { public List<Bar> children = new ArrayList<Bar>(); public List<StringBuilder> foo(List<String> foo) {return null; } public void bar(List<? extends String> param) {} } class Bar extends Foo<String> {} }
Print out
class java.lang.Stringclass com.javapuzzle.davidwang456.ClassTest$Barclass java.lang.Stringinterface java.lang.CharSequence
You will find that each type parameter is retained and can be obtained through the reflection mechanism at runtime. So what exactly is "type erasure"? At least something was erased, right? Yes. In fact, everything except structured information is erased - here structured information refers to information related to the structure of the class rather than the flow of program execution. In other words, metadata related to the class, its fields, and the type parameters of its methods are preserved and can be obtained through reflection.
This article comes from php Chinese website, java tutorial column, welcome to learn!
The above is the detailed content of Can Java type erasure really completely erase all information?. For more information, please follow other related articles on the PHP Chinese website!