Pourquoi l'autoboxing Java ne s'étend-il pas aux invocations de méthodes de types autoboxés ?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

Question

Je veux convertir une primitive en chaîne et j'ai essayé :

myInt.toString();

Cela échoue avec l'erreur :

int cannot be dereferenced

Maintenant, je comprends que les primitives ne sont pas des types référence (c’est-à-dire pas un objet) et ne peuvent donc pas avoir de méthodes.Cependant, Java 5 a introduit l'autoboxing et le unboxing (à la C#...ce que je n'ai jamais aimé en C#, mais ce n'est pas la question).Donc, avec l'autoboxing, je m'attendrais à ce que ce qui précède convertisse myInt en Integer, puis appelle toString() à ce sujet.

De plus, je crois que C# autorise un tel appel, sauf si je me souviens mal.S'agit-il simplement d'une lacune malheureuse de la spécification Java d'autoboxing/unboxing, ou y a-t-il une bonne raison à cela ?

Était-ce utile?

La solution

L'autoboxing/unboxing Java ne va pas jusqu'à vous permettre de déréférencer une primitive, donc votre compilateur l'empêche.Votre compilateur sait toujours myInt comme un primitif.Il y a un article sur ce problème à l'adresse jcp.org.

L'autoboxing est principalement utile lors de l'affectation ou du passage de paramètres - vous permettant de transmettre une primitive en tant qu'objet (ou vice versa), ou d'attribuer une primitive à un objet (ou vice versa).

Donc malheureusement, il faudrait procéder comme ceci :(félicitations Patrick, je suis passé à ta façon)

Integer.toString(myInt);

Autres conseils

Idem pour ce que Justin a dit, mais vous devriez plutôt faire ceci :

Integer.toString(myInt);

Il enregistre une allocation ou deux et est plus lisible.

Une autre façon de procéder consiste à utiliser :

String.valueOf(myInt);

Cette méthode est surchargée pour chaque type primitif et Object.De cette façon, vous n’avez même pas à penser au type que vous utilisez.Les implémentations de la méthode appelleront pour vous la méthode appropriée du type donné, par ex. Integer.toString(myInt).

Voir http://java.sun.com/javase/6/docs/api/java/lang/String.html.

Semble être une lacune de la spécification pour moi

Il y a d'autres défauts et c'est un sujet subtil.Vérifier ce dehors:

public class methodOverloading{
   public static void hello(Integer x){
      System.out.println("Integer");
   }

   public static void hello(long x){
      System.out.println("long");
   }

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

Ici, "long" serait imprimé (je ne l'ai pas vérifié moi-même), car le compilateur choisit l'élargissement plutôt que l'autoboxing.Soyez prudent lorsque vous utilisez l'autoboxing ou ne l'utilisez pas du tout !

La syntaxe valide la plus proche de votre exemple est

((Integer) myInt).toString();

Lorsque le compilateur a terminé, cela équivaut à

Integer.valueOf(myInt).toString();

Cependant, cela ne fonctionne pas aussi bien que l'utilisation conventionnelle, String.valueOf(myInt), car, sauf cas particuliers, il crée une nouvelle instance d'Integer, puis la jette immédiatement, ce qui entraîne davantage de déchets inutiles.(Une petite plage d'entiers est mise en cache et l'accès se fait par un tableau.) Peut-être que les concepteurs de langage voulaient décourager cette utilisation pour des raisons de performances.

Modifier:J'apprécierais que le(s) votant(s) défavorable(s) expliquent pourquoi cela n'est pas utile.

En C#, les entiers ne sont pas des types référence et ne doivent pas non plus être encadrés pour que ÀChaîne() être appelé.Ils sont cependant, ils sont considérés comme des objets dans le Framework (en tant que ValueType, ils ont donc une sémantique de valeur).Dans le CLR, les méthodes sur les primitives sont appelées en les chargeant « indirectement » sur la pile (ldind).

Comme tout le monde l'a souligné, l'autoboxing vous permet de simplifier certains codes, mais vous ne pouvez pas prétendre que les primitives sont des types complexes.

Aussi intéressant : "L'autoboxing est un hack au niveau du compilateur" en Java.L'autoboxing est fondamentalement une étrange bidouille ajoutée à Java.Vérifier ce post pour plus de détails sur à quel point c'est étrange.

Il serait utile que Java définisse certaines méthodes statiques pour fonctionner sur les types primitifs et intègre dans le compilateur du sucre syntaxique afin que

5.asInteger

serait équivalent à

some.magic.stuff.Integer.asInteger(5);

Je ne pense pas qu'une telle fonctionnalité entraînerait une incompatibilité avec tout code compilé selon les règles actuelles, et elle contribuerait à réduire l'encombrement syntaxique dans de nombreux cas.Si Java encadrait automatiquement les primitives déréférencées, les gens pourraient supposer qu'il mappait la syntaxe de déréférencement aux appels de méthodes statiques (ce qui est effectivement ce qui se passe dans .NET), et donc que les opérations écrites sous cette forme n'étaient pas plus coûteuses qu'elles ne le seraient. les invocations de méthodes statiques équivalentes.Ajout d'une nouvelle fonctionnalité de langage qui encouragerait les gens à écrire du mauvais code (par ex.primitives déréférencées par auto-boxing) ne semble pas être une bonne idée, même si autoriser des méthodes de style déréférencement pourrait l'être.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top