1. Toutes les classes héritentObject
Toutes les classes en Java héritent implicitement de la Objectclasse.
Nous analyserons ce qu'est l'héritage et son fonctionnement en Java dans la quête Java Core. Pour l'instant, nous allons considérer un fait simple qui en découle :
Un objet de n'importe quelle classe peut être assigné à une Objectvariable. Exemple:
| Code | Note |
|---|---|
|
La ovariable stocke une référence à un Scannerobjet |
|
La ovariable stocke une référence à un Stringobjet |
|
La ovariable stocke une référence à un Integerobjet |
|
La ovariable stocke une référence à un Stringobjet |
C'est là que s'arrêtent les bonnes nouvelles. Le compilateur ne garde pas trace du type d'objet d'origine enregistré dans une Objectvariable, vous ne pourrez donc pas appeler de méthodes sur l'objet enregistré autres que les méthodes de la Objectclasse.
Si vous devez appeler les méthodes associées au type d'origine de l'objet, vous devez d'abord enregistrer une référence à celui-ci dans une variable du type correct, puis appeler les méthodes sur cette variable :
| Code | Note |
|---|---|
|
Le programme ne compilera pas. La Objectclasse n'a pas nextInt()de méthode. |
|
Cela fonctionnera. Ici, nous enregistrons une référence à un Scannerobjet dans une Scannervariable à l'aide d'un opérateur de transtypage . |
Vous ne pouvez pas simplement assigner une Objectvariable à une variable Scanner, même si la Objectvariable stocke une référence à un Scannerobjet. Mais vous pouvez le faire si vous utilisez l' opérateur de transtypage , que vous connaissez déjà. Voici son aspect général :
Type name1 = (Type) name2;
Où name1est le nom d'une Typevariable, et name2est le nom d'une Objectvariable qui stocke une référence à un Typeobjet.
Transtypage
Si le type de la variable et le type de l'objet ne correspondent pas, alors un ClassCastExceptionsera lancé. Exemple:
| Code | Note |
|---|---|
|
Une erreur se produira lors de l'exécution : un ClassCastExceptionsera renvoyé ici |
Il existe un moyen d'éviter cette erreur en Java : nous le faisons en vérifiant le type de l'objet stocké dans une variable :
name instanceof Type
L' instanceofopérateur vérifie si la namevariable est un Typeobjet.
Par exemple, recherchons une chaîne dans un tableau d'objets divers :
| Code | Note |
|---|---|
|
L'autoboxing convertira ces valeurs en Integer, Stringet Double, respectivement. Boucle sur le tableau d'objets Si l'objet est un StringEnregistrer dans une Stringvariable Afficher la variable à l'écran. |
2. Pourquoi les génériques sont apparus — collections
Revenons aux collections.
Dès que les développeurs Java ont créé la ArrayListclasse, ils ont voulu la rendre universelle, afin qu'elle puisse stocker n'importe quel type d'objet. Ils ont donc utilisé un tableau de Objects pour stocker les éléments.
La force de cette approche est que vous pouvez ajouter un objet de n'importe quel type à la collection.
Bien sûr, il y a plusieurs faiblesses.
Inconvénient 1.
Il était toujours nécessaire d'écrire un opérateur de conversion de type lors de la récupération d'éléments d'une collection :
| Code | Note |
|---|---|
|
Créer une collection pour stocker les références aux Objectobjets Remplir la collection avec des nombres 10, 20, ... 100; Additionner les éléments de la collection Le typage est nécessaire |
Inconvénient 2.
Il n'y avait aucune garantie qu'une collection contienne un type spécifique d'élément
| Code | Note |
|---|---|
|
Créer une collection pour stocker des références à Objectdes objets Nous remplissons la collection avec des nombres représentés sous forme Doubled'objets : 0.0, 2.5, 5.0, ... Additionner les éléments de la collection Il y aura une erreur : a Doublene peut pas être transtypé en anInteger |
Les données peuvent être placées dans la collection n'importe où :
- dans une autre méthode
- dans un autre programme
- à partir d'un dossier
- sur le réseau
Inconvénient 3.
Les données de la collection peuvent être modifiées accidentellement.
Vous pouvez transmettre une collection remplie de vos données à une méthode. Cette méthode, écrite par un programmeur différent, ajoute ses données à votre collection.
Le nom de la collection n'indique pas clairement quels types de données peuvent y être stockés. Et même si vous donnez un nom clair à votre variable, une référence à celle-ci peut être transmise à une douzaine de méthodes, et ces méthodes ne sauront certainement rien du nom d'origine de la variable.
3. Génériques

En Java, tous ces problèmes sont éliminés par ce truc sympa appelé les génériques.
En Java, les génériques signifient la possibilité d'ajouter des paramètres de type aux types. Le résultat est un type composite complexe. La vue générale d'un tel type composite est la suivante :
ClassName<TypeParameter>
Il s'agit d'une classe générique. Et il peut être utilisé partout où vous utilisez normalement des cours.
| Code | Description |
|---|---|
|
Création de variables |
|
Création d'objets |
|
Création de tableaux |
Seules Integerles variables peuvent être stockées dans une telle collection :
| Code | Description |
|---|---|
|
ArrayListcollection avec Integerdes éléments Ceci est autorisé Et cela fonctionnera également
Boîte automatique
Mais ce n'est pas autorisé : erreur de compilation |
Vous apprendrez à créer vos propres classes avec des paramètres de type dans la quête Java Collections. Pour l'instant, nous allons voir comment les utiliser et comment ils fonctionnent.
4. Comment fonctionnent les génériques
En fait, les génériques sont terriblement primitifs.
Le compilateur remplace simplement les types génériques par des types ordinaires. Mais lorsque des méthodes d'un type générique sont utilisées, le compilateur ajoute un opérateur de transtypage pour convertir les paramètres en paramètres de type :
| Code | Ce que fait le compilateur |
|---|---|
|
|
|
|
|
|
|
|
Supposons que nous ayons une méthode qui additionne les nombres dans une collection d'entiers :
| Code | Ce que fait le compilateur |
|---|---|
|
|
En d'autres termes, les génériques sont une sorte de sucre syntaxique, tout comme l'autoboxing, mais un peu plus. Avec l'autoboxing, le compilateur ajoute des méthodes pour convertir an inten an Integeret vice versa, et pour les génériques, il ajoute des opérateurs de transtypage.
Une fois que le compilateur a compilé vos classes génériques avec des paramètres de type, elles sont simplement converties en classes ordinaires et en opérateurs de transtypage. Les informations sur les arguments de type passés aux variables de types génériques sont perdues. Cet effet est également appelé effacement de type .
Parfois, les programmeurs écrivant des classes génériques (classes avec des paramètres de type) ont vraiment besoin des informations sur les types passés en arguments. Dans la quête Java Collections, vous apprendrez comment gérer cela et ce que cela implique.
5. Quelques faits sur les génériques
Voici quelques faits intéressants sur les génériques.
Les classes peuvent avoir plusieurs paramètres de type. Cela ressemble à ceci :
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
En fait, ce n'est pas vraiment surprenant. Partout où le compilateur peut ajouter un opérateur à convertir en un type, il peut ajouter plusieurs opérateurs de transtypage.
Exemples:
| Code | Note |
|---|---|
|
Le putpremier paramètre de la méthode est un Integer, et le second est unString |
Les types génériques peuvent également être utilisés comme paramètres . Cela ressemble à ceci :
ClassName<TypeParameter<TypeParameterParameter>>
Supposons que nous voulions créer une liste qui stockera des listes de chaînes. Dans ce cas, nous obtiendrons quelque chose comme ceci :
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Les types génériques (types avec des paramètres de type) peuvent également être utilisés comme types de tableau. Cela ressemble à ceci :
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Il n'y a rien de magique ici : les crochets indiquent simplement le nom du type :
| Code | Contrepartie non générique |
|---|---|
|
|
|
|
|
|
GO TO FULL VERSION