Conversion de variables en Java


Je me demande si quelqu'un pourrait me dire comment casting fonctionne? Je comprendsquand je devrais le faire, mais pas vraiment comment cela fonctionne. Sur les types de données primitifs, je comprends partiellement mais quand il s'agit de lancer des objets, je ne comprends pas comment cela fonctionne.

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

Author: ivanleoncz, 2011-03-13

5 answers

Lancer en Java n'est pas magique, c'est vous dire au compilateur qu'un objet de type A est en fait de type B plus spécifique, et ainsi accéder à toutes les méthodes sur B que vous n'auriez pas eu autrement. Vous n'effectuez aucune sorte de magie ou de conversion lors de la coulée, vous dites essentiellement au compilateur "croyez-moi, je sais ce que je fais et je peux vous garantir que cet objet à cette ligne est en fait un type ."Par exemple:

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

Le ci-dessus est bien, pas magique et tout va bien. L'objet stocké dans o est en fait une chaîne, et nous pouvons donc lancer une chaîne sans aucun problème.

Il y a deux façons que cela pourrait mal tourner. Tout d'abord, si vous lancez entre deux types dans des 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 sont dans la même hiérarchie mais toujours un cast invalide, alors un ClassCastException sera lancé à durée d'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.) Toutefois, si vous voulez aller dans l'autre sens autour de vous besoin d'un cast-tous les nombres ne sont pas des Entiers (ainsi que des entiers que nous avons 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 c'est un choix unique et évident!

Concernant l'utilisation de la coulée, vous voyez toujours le besoin dans certaines bibliothèques. Pré Java-5 il a été fortement utilisé dans les collections et diverses autres classes, car toutes les collections ont travaillé sur ajouter des objets, puis lancer le résultat que vous avez récupéré la collection. Cependant, avec l'avènement des génériques, une grande partie de l'utilisation pour le casting a disparu - il a été remplacé par des génériques qui fournissent une alternative beaucoup plus sûre, sans le potentiel de ClassCastExceptions (en fait, si vous utilisez des génériques proprement et qu'il se compile sans avertissement, vous avez la garantie que vous n'obtiendrez jamais une ClassCastException.)

 182
Author: Michael Berry, 2017-02-18 11:23:00

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

 7
Author: sandrstar, 2015-04-01 00:36:07

Supposons que vous vouliez lancer 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 et non un parent de la classe String (et le compilateur se plaint).

, Mais vous pourriez lancer votre String à Object, car un String est un Object (Object est-parent). Ensuite, vous pouvez convertir cet objet en File, car un fichier est un Object.

Donc, toutes vos opérations sont "légales" d'un point de vue de frappe au moment de la compilation, mais c'est le cas ne signifie pas que cela fonctionnera à l'exécution !

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

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

Exception in thread "main" java.lang.ClassCastException:
    java.lang.String cannot be cast to java.io.File
 5
Author: Christophe Roussy, 2018-12-26 11:37:04

Lancer une référence ne fonctionnera que si c'est un instanceof de ce type. Vous ne pouvez pas jeter des 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.
 3
Author: asgs, 2011-03-13 12:48:08

La bonne façon est la suivante:

Integer i = Integer.class.cast(obj);

La méthode cast() est une alternative beaucoup plus sûre au casting à la compilation.

 3
Author: yegor256, 2020-02-20 14:31:50