# Programmation Java/Transtypage

* Introduction
* La notion de machine virtuelle
* Installation
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Premier programme
** Commentaires
** Types de base
** Opérateurs
** Conditions
** Bloc de portée
** Itérations
** Tableaux
* Les classes en Java
** Membres
** Modificateurs d'accès
** Héritage
** Encapsulation
** Polymorphisme
** Classes abstraites
** Interfaces
** Classes internes
** Transtypage
** Types génériques
** Instanciation et cycle de vie
** « this »
** Objets comparables et clés
** Énumérations
** Exceptions
** Packages
* Classes de base
** Collections
** Nombre de taille arbitraire
** Tags Javadoc
** Annotations
** Entrées sorties
** Threads et synchronisation
** Méthodes natives
** Réflexion
** Regex
** JUnit
* Conclusion
* Exemples en Java
** Générer un carré magique
** Générer un triangle de Sierpiński
** XML
** Swing
*** Un premier exemple
*** Formulaire avec boutons sur image
*** Calcul de somme
*** Calcul de distance
* Annexes
** Les outils de base fournis avec le Java Development Kit
** Créer une archive Java
** Paramétrer la JVM
** Liste des mots réservés
** Débogage
** Java et les autres langages
* Introduction
* La notion de machine virtuelle
* Installation
** NetBeans
** Eclipse
** Visual Studio Code
* Bases du langage
** Premier programme
** Commentaires
** Types de base
** Opérateurs
** Conditions
** Bloc de portée
** Itérations
** Tableaux
* Les classes en Java
** Membres
** Modificateurs d'accès
** Héritage
** Encapsulation
** Polymorphisme
** Classes abstraites
** Interfaces
** Classes internes
** Transtypage
** Types génériques
** Instanciation et cycle de vie
** « this »
** Objets comparables et clés
** Énumérations
** Exceptions
** Packages
* Classes de base
** Collections
** Nombre de taille arbitraire
** Tags Javadoc
** Annotations
** Entrées sorties
** Threads et synchronisation
** Méthodes natives
** Réflexion
** Regex
** JUnit
* Conclusion
* Exemples en Java
** Générer un carré magique
** Générer un triangle de Sierpiński
** XML
** Swing
*** Un premier exemple
*** Formulaire avec boutons sur image
*** Calcul de somme
*** Calcul de distance
* Annexes
** Les outils de base fournis avec le Java Development Kit
** Créer une archive Java
** Paramétrer la JVM
** Liste des mots réservés
** Débogage
** Java et les autres langages
[ Modifier le sommaire ]
Le transtypage (ou cast) est la conversion d'une expression d'un certain type en une expression d'un autre type.

### Transtypage implicite

On peut affecter à un champ ou une variable d'un type donné une expression de type moins élevé dans la hiérarchie des types. De même, une méthode ou un constructeur attendant un argument d'un type donné peut recevoir en argument effectif une expression de type moins élevé que celui indiqué dans sa déclaration. L'expression fournie sera dans ce cas automatiquement convertie en le type attendu, sans que l'utilisateur ait besoin d'expliciter cette conversion. Toute tentative de conversion implicite d'un type vers un type qui n'est pas plus haut dans la hiérarchie des types déclenchera une erreur au moins à l'exécution, ou dès la compilation si elle est détectable statiquement.

#### Cas des types primitifs

Dans le cas des types primitifs, la hiérarchie est la suivante : byte est plus bas que short, short plus bas que int, char plus bas que int, int plus bas que long, long plus bas que float, float plus bas que double. Le type boolean est incomparable avec les autres types de base. On peut par exemple assigner à une variable de type float une expression de type int égale à 3 : l'expression 3 sera, avant affectation, convertie en float (3.0). Cette forme de conversion est réversible : on peut, après passage de int à float, reconvertir l'expression de type float résultante en int par une conversion explicite (voir ci-dessous) et retrouver la même valeur.
Le type déterminé statiquement pour les arguments d'opérateurs arithmétiques est le premier type à partir de int dans lequel peuvent être convertis les types de tous les arguments. Les expressions constantes sont d'autre part typées statiquement en le premier type à partir de int permettant leur représentation.

##### Typage par suffixe

Par défaut les entiers sont typés en Integer mais un suffixe peut les spécifier Long :

#### Cas des types références

La classe d'un objet ne peut évidemment être convertie : durant toute sa durée de vie, il s'agit toujours de la classe dans laquelle est défini le constructeur employé lors de sa création. Le type d'une référence peut en revanche être converti selon les règles suivantes :
* Si A est ancêtre de la classe B, alors toute expression de type "référence vers B" peut être implicitement convertie en le type "référence vers A".
* Si I est une interface implémentée par la classe B, toute expression de type "référence vers B" peut être implicitement convertie en le type "référence vers I".
* Si J est une interface étendant l'interface I, toute expression de type "référence vers J" peut être implicitement convertie en le type "référence vers I".
Dans l'exemple ci-dessous, on fait pointer trois références a, i, j, b, c vers un même objet de classe C :
La même règle permet de convertir toute référence en une référence de type Object :

#### Visibilité des champs et méthodes après transtypage, liaison dynamique

Soit r une référence de type "référence vers X", pointant vers un certain objet de classe C. D'après les règles ci-dessus, X est donc soit une classe (concrète ou abstraite) ancêtre de C, soit une interface implémentée par C :
* Les seuls champs accessibles via r sont ceux visibles dans X (déclarés dans X ou hérités, et visibles dans le contexte de r). La valeur liée à r.champ est celle liée à this.champ dans X.
* Seules les méthodes dont le nom est visible (par déclaration ou par héritage) dans X sont invocables sur r. L'implémentation exécutée lors d'une invocation de la forme r.méthode(..) sera l'implémentation de la méthode de même nom et de même signature dans la classe de l'objet, et non l'implémentation vue dans X. Le nom de la méthode est dit lié dynamiquement à l'implémentation de cette méthode dans la classe de l'objet.

#### Cas des conversions vers String

Toute expression peut être convertie implicitement (ou explicitement) dans le type "référence vers String". Dans le cas où cette expression n'est pas statiquement constante, il y a alors création dynamique d'un objet de classe String représentant la valeur de cette expression, et l'expression résultant devient une référence vers cet objet.

### Transtypage explicite

Le type d'une expression peut également être explicitement converti avec la syntaxe suivante :
Où expression est l'expression à convertir. S'il s'agit d'une expression composée, il faut l'encadrer par des parenthèses. La conversion explicite d'une expression doit être utilisée à chaque fois que l'on souhaite convertir une expression dans un type qui n'est pas plus haut dans la hiérarchie des types. Dans le cas des types numériques, cette conversion n'est sans pertes que si le type cible permet de représenter la même valeur. Dans le cas contraire, la valeur choisie dépend du type initial et du type cible. Dans le passage de float à int, la valeur choisie est par exemple la valeur entière de la valeur initiale :
Pour les types de références, la conversion est libre : une référence de type quelconque peut être explicitement convertie en toute référence dont le type permet de manipuler l'objet référencé, selon les règles ci-dessus. La non-validité de cette conversion n'est en général pas détectable avant l'exécution :
Ces conversions "descendantes" sont bien sûr propices aux erreurs. L'opérateur instanceof permet de vérifier la validité d'une conversion avant de l'effectuer :
L'opérateur instanceof et les conversions supportent également les tableaux (à partir d'un objet de type Object) :

### Autoboxing

Java 5 introduit un mécanisme permettant la simplification du transtypage, appelé autoboxing. Ce mécanisme permet d'utiliser indifféremment les types primitifs et les classes wrappers. Exemple :
Avant Java 5, il fallait écrire :
Alors qu'avec Java 5, il n'est plus nécessaire de passer par parseInt :
On voit que les int et les Integer sont utilisés indifféremment.
Toutefois, il n'est pas possible de déclarer un type générique avec un type primitif. Il faut utiliser la classe englobante correspondante.
Exemple :
Les limites de l'autoboxing est qu'il ne concerne que chaque type primitif et sa classe englobante respective. Par exemple le code suivant renvoie l'erreur inconvertible types en voulant passer du String au Float :
Il faut donc écrire :

## Références

* ↑ http://docs.oracle.com/javase/tutorial/java/data/converting.html