J'étudie des génériques dans cette période et j'ai trouvé ce mystère pour moi.
Considérons la classe factice suivante: p> à cause de l'effacement , au moment de l'exécution, le type de retour T [] de la méthode Getarray () est transformé en un objet [], qui est totalement raisonnable pour moi. P> Si nous accédons à cette méthode telle qu'elle est (c.getarray ()) Aucune exception n'est lancée, mais si nous essayons d'appeler des méthodes sur le tableau retourné, par exemple C.Array (). GetClass () ou si nous essayons d'accéder à un champ, par exemple C.GetARRAY () .Longueur, puis l'exception suivante est lancée: P> Exception dans le fil "Main" Java.lang.classcastException:
[Ljava.lang.Object; ne peut pas être coulé à [ljava.lang.Integer; p>
BlockQuote> Pourquoi cette exception est-elle jetée?
Pourquoi n'est-ce pas jeté aussi pour l'appel de C.GetARRAY () simple?
Pourquoi essaie-t-il de lancer entier [] si nous appelons simplement getclass () ou d'accéder à la longueur?
Sont getclass () et la longueur non disponibles aussi pour l'objet []? P> Merci d'avance pour votre nombre (j'espère) et explicite (j'espère que cela aussi) réponses. P> P>
3 Réponses :
La raison de l'exception est que le compilateur attend un Pour que ce soit correct, il faut la classe actuelle de T, afin de créer des instances. P> entier [] code> mais reçoit un objet [] code>. Il a ajouté une distribution d'exécution - sur les sites d'appel de getarray code>. Ces moulages ont découvert le couché, le mannequin, sans effet dans votre constructeur. (double[][][][][][]) Array.newInstance(double.class, 3, 3, 3, 3, 3, 6);
Mais je ne peux pas comprendre pourquoi il ne se plaint pas de C.Getarray () mais cela fait pour C.GetARRAY (). GetClass (). Ce qui me conduit fou est que c.getarray () est bien alors que c.getarray (). GetClass () n'est pas. Pourquoi le compilateur ne se plaint que pour le second? Dans le cas de C.GetARRAY (), la distribution non fonctionnelle devrait également se produire.
Vous n'édorciez pas g.getarray ().
Je n'ai pas pu trouver l'endroit exact dans les JLS qui dit que c'est le comportement, mais je pense que la raison est comme ceci:
L'expression: p>
15: checkcast #5 // class "[Ljava/lang/Integer;"
18: astore_1
19: aload_1
La mauvaise distribution se produit dans entier [] arr = (entier []) C.GETARRAY (); code>, non? Donc, si c.getarray (). Getclass () code> échoue, c.getarray () code> doit échouer de la même manière parce que la distribution est effectuée avant le getclass () < / Code> Invocation.
Non, je ne pense pas que oui - c'est le déséroférance de c.getarray () code> qui semble causer le problème. Par exemple, system.out.println (c.getarray ()) code> fonctionne bien; Mais cela invoque le system.out.println (objet) code> surcharge, qui ne nécessite pas la distribution.
C'est intéressant, merci. Si system.out.println (c.getarray ()) code> fonctionne bien parce que l'utilisation de l'objet ne serait pas la même pour c.getarray (). Getclass () code >? Je veux dire, getclass () code> est une méthode d'objet, de sorte que cela devrait fonctionner de toute façon. Où suis-je tort?
Lorsque vous faites un casting non sécurisé non sécurisé, il peut ne pas provoquer une exception quelque part. Vous n'êtes pas garanti d'obtenir une exception quelque part. P>
Dans ce cas, si vous obtenez une exception dépend de la question de savoir si le compilateur a inséré une distribution dans le code effacé pour lancer le résultat de l'appel à Dans chacun des trois cas, le compilateur est autorisé à insérer une distribution (car il est autorisé à supposer que le résultat est Pourquoi ce compilateur n'entraînerait-il pas de distribution dans le premier cas et insérerait-il une distribution dans les deuxième et troisième cas? Une explication évidente serait que dans le premier cas, le résultat est évidemment inutilisé, il est donc très simple de déterminer qu'un casting est inutile. Dans les deuxième et troisième cas, pour déterminer qu'une distribution est inutile nécessiterait de regarder la manière dont l'expression est utilisée pour voir que cela fonctionnera également avec Un autre compilateur peut insérer des moulages dans les trois cas. Et un autre compilateur pourrait ne pas avoir de moulage dans les trois cas. Vous ne pouvez pas compter sur elle. P> entier [] code>. Dans ce cas, il semble qu'un casting a été inséré dans les deuxième et troisième cas, mais pas le premier cas. P>
entier [] code> ou ne pas insérer une distribution (car l'expression est utilisée. de telle manière que nécessitent uniquement objet [] code> dans les trois). Insertion d'une mise en forme ou non à la mise en œuvre du compilateur particulier pour décider. P>
objet [] code>; Et c'est une analyse assez compliquée. Les auteurs du compilateur ont probablement opté pour une approche simple où ils ne sautent que lorsque le résultat n'est pas utilisé. P>
Afin de désirer la valeur de
c.getarray () code>, une référence à celle-ci doit être stockée temporairement sur la pile. Je peux imaginer que JLS dit - quelque part, toujours à la recherche - que cette variable temporaire doit être vérifiée pour voir s'il s'agit du type inersidé (puisque vous connaissez le type non alinéa).En effet, cela fonctionne si vous faites la déséroferience dans une méthode comme
statique Void FOO (conteneur C) {C.GETARRAY (). GetClass (); } code> Il y a une différence intéressante dans le bytecode si vous changez code> vers code>: avec
integer code>, il y a une vérificationcode> instruction (la raison duClasscastException code>); Avec l'objet code> code>, aucunCheckcast code> est ajouté. Compréhensible, puisque tous lest [] code> peuvent être distribués surobjet [] code>; juste surprenant que cela entraîne différents bytecodes.@Matsemann parce que je n'ai pas vraiment de réponse :) Je fais des observations.
La distribution à
entier [] code> sur le site d'appel degetarray () code> n'est pas différent, linguistique, que la distribution àentier code> sur le site d'appel deget () code>. (Ceci, BTW, c'est pourquoiCollection.Tearray () Code> RetoursObjet [] CODE> plutôt queT [] CODE> - Il ne veut pas mentez-vous et dites qu'il retourne unentier [] code> quand il renvoie vraiment un objet[] code>.)