Intervieweur : Parlez-moi du mécanisme générique de Java.
(Partage vidéo d'apprentissage : Tutoriel vidéo Java)
Réponse de la version Lite
Lors du développement de Java, en utilisant la syntaxe diamant <, Make une classe, une interface ou une méthode possède un groupe de classes qui acceptent une référence générique comme paramètre. La classe générique est finalement définie par les règles entre crochets. La classe générique est généralement représentée par une lettre majuscule, généralement la lettre T, et. est ensuite transmis par le compilateur Java Lors de la compilation, les génériques seront effacés, remplacés en fonction de la classe spécifique utilisée, et le bytecode de la classe sera généré, de sorte que les génériques soient transparents pour le Jvm.
Réponse de la version Deluxe
Les génériques ont été officiellement introduits dans JDK1.5
Contexte de Java introduisant les génériques
Les collections Java autorisent plusieurs types, par exemple,
List list=new ArrayList(); list.add("String"); list.add(1024);
C'était un usage courant avant le JDK 1.5. Même s'il est placé sous le JDK actuel, il est autorisé. Ensuite, l'utilisation de cette collection causera certains problèmes. collection sait quels types sont placés dans la collection. Les autres appelants ne peuvent pas en être sûrs. De cette façon, dans les grands projets, des problèmes peuvent facilement survenir si l'appelant transfère de force un objet dans la collection, une erreur se produit. sera signalé. Ce type d'erreur ne peut pas être trouvé dans la phase de compilation à ce moment-là, et ne peut être trouvé que pendant l'exécution. Afin de résoudre des problèmes similaires, le JDK a introduit des génériques.
Types génériques
Après l'introduction des génériques, il est possible de vérifier si le type répond aux exigences lors de la phase de compilation, éliminant ainsi dans une large mesure la conversion de type aveugle. Les génériques fonctionnent principalement dans le compilateur. Après la compilation, la JVM ne peut pas percevoir les génériques lorsqu'elle est en cours d'exécution. Les génériques sont divisés en génériques ordinaires et génériques génériques.
1. Génériques ordinaires
Comme son nom l'indique, ce type de générique prend en charge n'importe quel type lors de l'appel, mais lors de l'appel, les génériques situés à gauche et à droite du signe égal doivent être cohérent. Le diamant sur le côté droit de JDK1.7 peut être omis.
class Test<T>{...} //声明时 Test<Integer> test = new Test<Integer>(); //调用时 Test<Integer> test = new Test(); //1.7调用时
3. Génériques délimités
<?>//无界泛型,任意类型都匹配 <T extends ClassA>//有界泛型 - 继承自某父类 <T extends InterfaceB>//有界泛型 - 实现某接口 <T extends ClassA & InterfaceB & InterfaceC ... >//有界泛型 - 多重边界 <T super ClassC>//有界泛型 - 指定类父类
Effacement générique
Comme je viens de le mentionner, les génériques ne fonctionnent que lors de l'écriture de code et de la compilation, et Jvm charge les classes. Le runtime est invisible et transparent. car le compilateur efface les génériques lors de la compilation. Pour le dire simplement et vaguement, cela signifie : supprimez les crochets <> sur la classe ou la méthode, et suivez les règles dans les crochets. Passez à une classe spécifique, donc le Jvm. Le runtime ne sait pas qu'il y a eu des génériques dans ce code auparavant. Ceci est fait pour des raisons de compatibilité. Comme mentionné précédemment, les génériques n'ont été introduits que dans JDK1.5. De cette façon, même si des génériques sont introduits, certaines JVM n'ont pas besoin de majeures. changements, il leur suffit de changer de compilateur. Pour ce type de syntaxe que le compilateur peut percevoir, mais que la machine virtuelle ne peut pas, les gens appellent cette syntaxe sugar (suger). Après désugération, les informations sèches sont obtenues et transmises à. la machine virtuelle pour l'exécution.
(Tutoriel graphique recommandé : Tutoriel d'introduction à Java)
Mécanisme d'effacement générique
//Pair的泛型 public class Pair<T> { private T mFirst; private T mSecond; public T getmFirst() { return mFirst; } public void setmFirst(T mFirst) { this.mFirst = mFirst; } public T getmSecond() { return mSecond; } public void setmSecond(T mSecond) { this.mSecond = mSecond; } } //Pair的原始类型 //无论何时定义一个泛型类型,都会自动提供一个相应的 原始类型 public class Pair { private Object mFirst; private Object mSecond; public Object getFirst() { return mFirst; } public void setFirst(Object mFirst) { this.mFirst = mFirst; } public Object getSecond() { return mSecond; } public void setmSecond(Object mSecond) { this.mSecond = mSecond; } } //如果调用Pair<T extends String>编译擦除后得到如下= class Pair{ private String mFirst; private String mSecond; ... }
Lorsque des génériques sont utilisés comme paramètres d'entrée d'une méthode, après l'effacement , il est remplacé par la borne inférieure d'un générique générique, tel que la méthode add
public static void insertElements(List<? super A> list){ //Add进来的都是层级“小于等于”A的,也就是下界 list.add(new A()); list.add(new B()); list.add(new C()); }
Lorsqu'un générique est utilisé comme paramètre de retour d'une méthode, il est remplacé par la borne supérieure d'un générique générique après effacement, comme la méthode get
public void processElements(List<? extends A> elements){ //for循环挨个get list 里的数据,都当做A,也就是都当做上界 for(A a : elements){ System.out.println(a.getValue()); } }
Peu importe combien vous parlez d'effacement de type générique, peu importe le nombre de blogs que vous lisez, la définition officielle n'est pas aussi précise que la définition officielle. Document officiel d'Oracle sur l'effacement de type
Type Erasure Generics were introduced to the Java language to provide tighter type checks at compile time and to support generic programming. To implement generics, the Java compiler applies type erasure to: Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.Insert type casts if necessary to preserve type safety.Generate bridge methods to preserve polymorphism in extended generic types.Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
Pour plus de questions d'entretien, veuillez cliquer sur : questions et réponses d'entretien Java
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!