Home  >  Article  >  Java  >  How to use TypeToken in Java

How to use TypeToken in Java

王林
王林forward
2023-05-16 08:49:051572browse

Generic erasure

As we all know, Java's generics are only valid at compile time, and the generic type will be erased at runtime, that is, List< ;String> and List are actually List types at runtime.

Why choose this implementation mechanism? Can't you just erase it? It was 10 years after the birth of Java that I wanted to implement a concept similar to C templates, namely generics. Java's class library is a very valuable asset in the Java ecosystem. It must ensure backward compatibility (that is, existing code and class files are still legal) and migration compatibility (generalized code and non-generalized code can call each other). Based on the above Due to these two backgrounds and considerations, Java designers adopted a compromise implementation method of "type erasure".

At the same time, there is such a "hole" mechanism that prevents us from obtaining the specific types of generic parameters at will during runtime.

TypeToken

Use

Students who have used Gson know that they need to define a TypeToken type during deserialization. Like this

private Type type = new TypeToken>>(){}.getType();  //调用fromJson方法时把type传过去,如果type的类型和json保持一致,则可以反序列化出来  gson.fromJson(json, type);

Three questions

1. Why use TypeToken to define the deserialized type? As mentioned above, if you directly pass the types of List>, but because the runtime generics are erased, what you get is actually List, then the subsequent Gson will not Knowing that it needs to be converted to Map type, Gson will convert it to LinkedTreeMap type by default.

2.Why are there curly brackets {}? This brace is the essence. As we all know, in Java syntax, in this context, {} is used to define an anonymous class. This anonymous class inherits the TypeToken class, which is a subclass of TypeToken.

3. Why should we obtain the generic type through subclasses? This is the key to TypeToken being able to obtain the generic type. This is a clever method. The idea is like this, since the generics in List will be erased, then I use a subclass SubList extends List. In this case, will the parent class be genericized inside the JVM? What type of type is saved?

The generics of the parent class that my subclass needs to inherit have been determined. Sure enough, the JVM saves this part of the information, and it is saved in the Class information of the subclass.

So how do we obtain this information? Fortunately, Java provides an API:

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

In summary, for classes with generics, a ParameterizedType object is returned, for Object, interfaces and primitive types, null is returned, and for array classes, Object is returned. .class. ParameterizedType is a Java type that represents a type with generic parameters. After the introduction of generics in JDK1.5, all Classes in Java implement the Type interface. ParameterizedType inherits the Type interface. All Class classes containing generics will Implement this interface.

Debug it yourself and you will know what it returns.

Principle

The core method is the two sentences just mentioned, and the rest is very simple. Let’s look at the getType method of TypeToken

public final Type getType() {   //直接返回type      return type;    }

Look at the initialization of type

//注意这里用了protected关键字,限制了只有子类才能访问  protected TypeToken() {      this.type = getSuperclassTypeParameter(getClass());      this.rawType = (Class) $Gson$Types.getRawType(type);      this.hashCode = type.hashCode();    }      //getSuperclassTypeParameter方法    //这几句就是上面的说到    static Type getSuperclassTypeParameter(Class subclass) {      Type superclass = subclass.getGenericSuperclass();      if (superclass instanceof Class) {        throw new RuntimeException("Missing type parameter.");      }      ParameterizedType parameterized = (ParameterizedType) superclass;      //这里注意一下,返回的是Gson自定义的,在$Gson$Types里面定义的TypeImpl等,这个类都是继承Type的。      return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);    }

The above is the detailed content of How to use TypeToken in Java. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete