web-dev-qa-db-fra.com

Variation de variables dans Java

Je me demande si quelqu'un pourrait me dire comment fonctionne le casting? Je comprends quand Je devrais le faire, mais pas vraiment comment ça marche. Je comprends partiellement les types de données primitifs, mais je ne comprends pas comment cela fonctionne.

Comment un objet avec le type Object peut-il être soudainement transformé en, disons, MyType (juste un exemple), puis obtenir toutes les méthodes?

78
user626912

Lancer Java n'est pas magique, c'est dire au compilateur qu'un objet de type A est en fait de type plus spécifique B et donne ainsi accès à toutes les méthodes sur B que vous n'auriez pas eu autrement. Vous n’exécutez aucune sorte de magie ou de conversion lorsque vous effectuez un casting, vous dites essentiellement au compilateur "faites-moi confiance, je sais ce que je fais et je peux vous garantir que cet objet situé sur cette ligne est en fait un <Insert cast tapez ici>. " Par exemple:

Object o = "str";
String str = (String)o;

Ce qui précède est bon, pas magique et tout va bien. L'objet stocké dans o est en fait une chaîne et nous pouvons donc transtyper une chaîne sans aucun problème.

Il y a deux façons pour que cela puisse aller mal. Premièrement, si vous utilisez deux types de hiérarchies d'héritage complètement différentes, le compilateur saura que vous êtes idiot et vous arrêtera:

String o = "str";
Integer str = (Integer)o; //Compilation fails here

Deuxièmement, s’ils appartiennent à la même hiérarchie mais qu’ils ont toujours une distribution invalide, un ClassCastException sera lancé au moment de l’exécution:

Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here

Cela signifie essentiellement que vous avez violé la confiance du compilateur. Vous lui avez dit que vous pouvez garantir que l'objet est d'un type particulier, et ce n'est pas le cas.

Pourquoi avez-vous besoin de casting? Eh bien, pour commencer, vous n’en avez besoin que lorsque vous passez d’un type plus général à un type plus spécifique. Par exemple, Integer hérite de Number, donc si vous voulez stocker un Integer en tant que Number, alors c'est ok (puisque tous les entiers sont des nombres.) Cependant, si vous vous voulez faire l'inverse vous avez besoin d'un casting - tous les nombres ne sont pas des entiers (nous avons aussi Double, Float, Byte, Long, etc. ) Et même s'il n'y a qu'une seule sous-classe dans votre projet ou le JDK, quelqu'un pourrait facilement en créer une autre et la distribuer, vous n'avez donc aucune garantie, même si vous pensez que ce n'est qu'un choix évident!

En ce qui concerne l'utilisation pour le casting, vous en voyez toujours le besoin dans certaines bibliothèques. Avant Java-5, il était très utilisé dans les collections et diverses autres classes, car toutes les collections travaillaient à l’ajout d’objets, puis à la conversion du résultat obtenu. Cependant, avec l'avènement des génériques, une grande partie de l'utilisation du casting a disparu - elle a été remplacée par des génériques qui offrent une alternative beaucoup plus sûre, sans potentiel pour ClassCastExceptions (en fait, si vous utilisez les génériques proprement et compile sans avertissement, vous avez la garantie que vous ne recevrez jamais d’exception ClassCastException.)

173
Michael Berry

En fait, le casting ne fonctionne pas toujours. Si l'objet n'est pas un instanceof la classe à laquelle vous le transmettez vous obtiendrez un ClassCastException au moment de l'exécution.

7
sandrstar

Supposons que vous vouliez convertir un String en File (oui, cela n'a aucun sens), vous ne pouvez pas le lancer directement, car la classe File n'est pas un enfant ni un parent de la classe String (et le compilateur se plaint).

Mais vous pouvez convertir votre String en Object, car un String est un Object (Object est le parent). Vous pouvez ensuite convertir cet objet en File, car un fichier est un Object.

Ainsi, toutes vos opérations sont "légales" du point de vue de la frappe au moment de la compilation, mais cela ne signifie pas que cela fonctionnera au moment de l'exécution!

File f = (File)(Object) "Stupid cast";

Le compilateur autorisera cela même si cela n'a pas de sens, mais il se plantera lors de l'exécution avec cette exception:

Exception in thread "main" Java.lang.ClassCastException:
    Java.lang.String cannot be cast to Java.io.File
5
Christophe Roussy

Lancer une référence ne fonctionnera que s'il s'agit d'un instanceof de ce type. Vous ne pouvez pas lancer de références aléatoires. En outre, vous devez en savoir plus sur Casting Objects.

par exemple.

String string = "String";

Object object = string; // Perfectly fine since String is an Object

String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.
2
asgs