Gets the class reflection of a generic type

Source: Internet
Author: User
Tags tojson

The recent conversion between JSON and Java objects using Google's Gson package provides a good support for serialization and deserialization of classes that contain generics, and it's a bit of a sense to take the time to study it.

Because of the Java Generics Implementation mechanism, the type of generic parameters that are associated with generics are erased during runtime, and we cannot know the specific type of the generic parameter during run time (all generic types are object types at runtime).

But sometimes, we really need to know the types of generic parameters, such as the use of generic Java code serialization or deserialization, this time the problem becomes more difficult.

?
12345678 classFoo<T> {  T value;}Gson gson = new Gson();Foo<Bar> foo = new Foo<Bar>();gson.toJson(foo); // May not serialize foo.value correctlygson.fromJson(json, foo.getClass()); // Fails to deserialize foo.value as Bar

For the above class Foo<t>, it is not possible to serialize and deserialize objects of this class without knowing the specific type of T during operation. Gson solves this problem by using the TypeToken class.

?
12345678 TestGeneric<String> t = newTestGeneric<String>();  t.setValue("Alo");  Type type = new TypeToken<TestGeneric<String>>(){}.getType();    String gStr = GsonUtils.gson.toJson(t,type);  System.out.println(gStr);  TestGeneric t1 = GsonUtils.gson.fromJson(gStr, type);  System.out.println(t1.getValue());

TypeToken is very simple to use, as the above code, as long as the need to get the type of generic class as TypeToken generic parameters to construct an anonymous subclass, you can use the GetType () method to get to the generic class we used the generic parameter type.

The following is a simple analysis of the principle.

To get the type of a generic parameter, it is common practice to display the class type of the generic class as a private property of the generic class by displaying it in the constructor of a class that uses generics, which holds the type information for the generic class.

?
123456789101112131415161718 publicclassFoo<T>{  publicClass<T> kind;  publicFoo(Class<T> clazz){  this.kind = clazz; }  public T[] getInstance(){  return(T[])Array.newInstance(kind, 5); }  publicstaticvoidmain(String[] args){  Foo<String> foo = newFoo(String.class);  String[] strArray = foo.getInstance(); }}

Although this method can solve the problem, but each time to pass in a class parameter, it seems more troublesome. There is another solution to this problem in the Gson library.

The same is done to get the class type, which can be implemented in another way:

?
12345678910111213141516 publicabstract class Foo<T>{   Class<T> type;   public Foo(){  this.type = (Class<T>) getClass(); }         public static void main(String[] args) {     Foo<String> foo = new Foo<String>(){};  Class mySuperClass = foo.getClass();  } }

Declare an abstract parent class Foo, the anonymous subclass passes the generic class as the generic parameter of Foo to construct an instance, and then calls the GetClass method to get the class type of the subclass.

Although the class type of the anonymous subclass is obtained in another way, it does not directly pass in the class type of the generic parameter T, but also how to obtain the type of the generic parameter, which relies on the generic parameter information stored in Java's class bytecode. While Java's generic mechanism is the same for generics and non-generic classes during runtime, generic-related information is stored in a class file in the compiled Java source code, which is stored in the class byte-code constant pool, where a signature signature field is generated using the generic code. , the address of this constant pool is indicated by the signature signature field.

Detailed knowledge of the types of generic parameters stored in the class file can be found here: http://stackoverflow.com/questions/937933/ Where-are-generic-types-stored-in-java-class-files

The JDK provides a way to read the generic information, and with reflection, you can get the specific type of the generic parameter. Similarly, for the Foo object in the first code, the type of T in foo<t> can be obtained by the following code:

?
123 Type mySuperClass = foo.getClass().getGenericSuperclass();  Type type = ((ParameterizedType)mySuperClass).getActualTypeArguments()[0];System.out.println(type);

The result of the operation is class java.lang.String.

To analyze this code, the comments for the class Getgenericsuperclass () method are:

Returns the Type representing the direct superclass of the Entity (class, interface, primitive Type or void) represented B Y ThisClass.

If The superclass is a parameterized type, the type object returned must accurately reflect the actual type parameters use D in the source code. The parameterized type representing the superclass is created if it had not been created before. See the Declaration of parameterizedtype for the semantics of the creation process for parameterized types. If ThisClass represents either Theobject class, an interface, a primitive type, or void, then NULL is returned. If This object represents a array class then Theclass object representing Theobject class is returned

As a general rule, for classes with generics, return a Parameterizedtype object, return null for object, interface, and primitive type, and return Object.class for the array class. Parameterizedtype is a Java type that represents a type with a generic parameter, JDK1.5 introduces generics, all classes in Java implement the type interface, and Parameterizedtype inherits the type interface. All class classes that contain generics will implement this interface.

In the actual application also consider a lot of cases, such as obtaining the number of generic parameters to avoid array out of bounds, and so on, you can see the TypeToken class in Gson and Parameterizedtypeimpl class code.

Gets the class reflection of a generic type

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.