Effacement générique
Comme nous le savons tous, les génériques Java ne sont valides qu'au moment de la compilation, c'est-à-dire que List
Pourquoi choisir ce mécanisme de mise en œuvre ? Tu ne peux pas simplement l'effacer ? C'est 10 ans après la naissance de Java que j'ai souhaité implémenter un concept similaire aux templates C++, à savoir les génériques. La bibliothèque de classes Java est un atout très précieux dans l'écosystème Java. Elle doit garantir la compatibilité descendante (c'est-à-dire que le code et les fichiers de classe existants sont toujours légaux) et la compatibilité de migration (le code généralisé et le code non généralisé peuvent s'appeler). ce qui précède En raison de ces deux contextes et considérations, les concepteurs Java ont adopté une méthode de mise en œuvre de compromis « effacement de type ».
En même temps, il existe un tel mécanisme de « trou » qui nous empêche d'obtenir à volonté les types spécifiques de paramètres génériques pendant l'exécution.
TypeToken
Les étudiants qui ont utilisé
sont tous qu'ils doivent définir un type TypeToken lors de la désérialisation, comme ceci
private Type type = new TypeToken<List<Map<String, Foo>>>(){}.getType(); //调用fromJson方法时把type传过去,如果type的类型和json保持一致,则可以反序列化出来 gson.fromJson(json, type);
Trois questions
1 Pourquoi utiliser TypeToken pour le définir ? ? Comme mentionné ci-dessus, si vous transmettez directement les types de List
2. Pourquoi y a-t-il des accolades {} ? Cette attelle est l'essence. Comme nous le savons tous, dans la syntaxe Java, dans ce contexte, {} est utilisé pour définir une classe anonyme. Cette classe anonyme hérite de la classe TypeToken, qui est une sous-classe de TypeToken.
3. Pourquoi devrions-nous obtenir le type générique via des sous-classes ? C'est la clé pour que TypeToken puisse obtenir le type générique. C'est une méthode intelligente. L'idée est la suivante, puisque les génériques de List
Les génériques de la classe parent dont ma sous-classe doit hériter ont été déterminés, la JVM enregistre cette partie des informations, et elle est enregistrée dans les informations de classe de la sous-classe.
Alors, comment obtenons-nous ces informations ? Heureusement, Java fournit une API :
Type mySuperClass = foo.getClass().getGenericSuperclass(); Type type = ((ParameterizedType)mySuperClass).getActualTypeArguments()[0]; System.out.println(type);
En résumé, pour les classes avec des génériques, un objet ParameterizedType est renvoyé, pour Object, interfaces et types primitifs, null est renvoyé, et pour les classes tableau, Object.class est renvoyé. ParameterizedType est un type Java qui représente un type avec des paramètres génériques. Après l'introduction des génériques dans JDK1.5, toutes les classes en Java implémentent l'interface Type hérite de l'interface Type.
Déboguez-le vous-même et vous saurez ce qu'il renvoie.
Principe
La méthode de base est constituée des deux phrases que nous venons de mentionner, et le reste est très simple. Regardons la méthode getType de TypeToken
public final Type getType() { //直接返回type return type; }
Regardons l'initialisation de type
//注意这里用了protected关键字,限制了只有子类才能访问 protected TypeToken() { this.type = getSuperclassTypeParameter(getClass()); this.rawType = (Class<? super T>) $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]); }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!