web-dev-qa-db-fra.com

Comment les types "var" et raw se rejoignent-ils?

Je suis tombé sur un réponse qui suggère d'utiliser

var list = new ArrayList();

J'ai été surpris de trouver un type brut ici, et je me demande simplement: var utilise-t-il <> "Automatiquement?

(en attendant, la réponse a été modifiée pour utiliser <String>, mais je suis toujours curieux de savoir mais des "principes" ici)

J'ai vu d'autres questions telles que this , mais elles utilisent toutes l'opérateur diamant:

var list = new ArrayList<>();

Maintenant, je me demande simplement: var change-t-il la façon dont nous devrions (ne pas) utiliser les types bruts? Ou est-ce que cette suggestion de laisser de côté <> Est simplement une mauvaise pratique?

19
GhostCat

Je suis tombé sur une réponse qui suggère d'utiliser ...

J'ignorerais cette réponse, car comme vous le signalez, il utilise des types bruts et il tape list comme spécifiquement ArrayList. (Mise à jour: le répondeur a modifié leur réponse pour ajouter un type d'élément.) À la place:

List<AppropriateElementType> list = new ArrayList<>();

Selon le deuxième réponse que vous avez liée , var will oblige le compilateur à déduire un type d'élément du côté droit si vous incluez le <>, En choisissant le type le plus spécifique possible. Dans var list = new ArrayList<>();, ce serait ArrayList<Object>, Car il n'a rien de plus spécifique à choisir.

Mais , ceci:

var list = new ArrayList();

... sans <>, utilise un type brut (ArrayList), pas un type paramétré avec Object comme paramètre (ArrayList<Object>), qui est différent.


Si l'utilisation de list est suffisamment contenue (quelques lignes dans une méthode), le faire taper ArrayList<X> Plutôt que List<X> Peut être acceptable (dépend de votre style de codage), dans quel cas:

var list = new ArrayList<AppropriateElementType>();

Mais généralement, je préfère coder sur l'interface plutôt que sur la classe concrète, même avec les locaux. Cela dit, avec les sections locales, c'est c'est moins important qu'avec les membres d'instance, et var est pratique.

32
T.J. Crowder

Il est légal d'utiliser à la fois var et diamond, mais le type déduit changera:

var list = new ArrayList<>(); // DANGEROUS: infers as ArrayList<Object>

Pour son inférence, diamond peut utiliser le type cible (généralement, le côté gauche d'une déclaration) ou les types d'arguments constructeur. Si aucun n'est présent, il revient au type applicable le plus large, qui est souvent Object1.

Avec les méthodes diamond et génériques, des informations de type supplémentaires peuvent être fournies par des arguments réels au constructeur ou à la méthode, ce qui permet de déduire le type voulu1:

var list = List.of(BigInteger.ZERO); // OK: infers as List<BigInteger>
var list = new ArrayList<String>( ); // OK: infers as ArrayList<String>

Compte tenu de ce qui précède, je ne recommande pas d'effectuer les opérations suivantes (car vous obtiendrez le type brut ArrayList):

var list = new ArrayList(); // DANGEROUS: infers as ArrayList

Conclusion:

  1. N'utilisez pas de types bruts indépendamment de la présence ou de l'absence de var.
  2. Assurez-vous que les arguments de méthode ou de constructeur fournissent suffisamment d'informations sur le type pour que le type déduit corresponde à votre intention. Sinon, évitez d'utiliser les deux var avec diamond1.

1 - ( Consignes de style pour l'inférence de type variable locale: G6. Soyez prudent lorsque vous utilisez var avec diamant ou des méthodes génériques.

10
Oleksandr Pyrohov