L'efficacité de Java “Double Croisillon d'Initialisation”?

Dans Les Fonctions cachées de Java la réponse sommet mentionne Double Croisillon D'Initialisation, avec un très séduisant syntaxe:

Set<String> flavors = new HashSet<String>() {{
    add("vanilla");
    add("strawberry");
    add("chocolate");
    add("butter pecan");
}};

Cet idiome crée un anonyme intérieur de la classe avec juste un exemple de l'initialiseur, ce qui "peut utiliser n'importe quel [...] les méthodes dans le champ d'application".

Question principale: Est-ce que inefficace comme il en a l'air? Son utilisation soit limitée à des initialisations? (Et bien montrer!)

Deuxième question: Le new HashSet doit être le "ce" utilisée dans l'instance de l'initialiseur ... quelqu'un peut jeter de la lumière sur le mécanisme?

Troisième question: Est-ce un langage trop obscur à utiliser dans la production de code?

Résumé: très, Très gentil réponses, merci à tous. Sur la question (3), les gens ont senti la syntaxe devrait être clair (même si je recommande un commentaire occasionnel, surtout si votre code est de transmettre aux développeurs qui peuvent ne pas être familiers avec elle).

Sur la question (1), le code généré doit s'exécuter rapidement. L'extra .les fichiers de classe font du fichier jar de l'encombrement, et de ralentir le démarrage du programme légèrement (merci à @coobird de mesure qui). @Thilo a souligné que la collecte des ordures peut être affectée, et le coût mémoire pour le chargement des classes peut être un facteur dans certains cas.

Question (2) s'est avéré pour être le plus intéressant pour moi. Si j'ai bien compris les réponses, ce qui se passe dans DBI, c'est que l'anonyme intérieure classe étend la classe de l'objet en cours de construction par le nouvel opérateur, et a donc un "cette" valeur de référence l'instance en cours de construction. Très soigné.

Dans l'ensemble, DBI, me paraît être quelque chose d'une curiosité intellectuelle. Coobird et de l'autre, vous pouvez obtenir le même effet avec des Tableaux.asList, varargs méthodes, Google Collections, et le projet de Java 7 de la Collection de littéraux. Nouveaux JVM langues comme Scala, JRuby, et Groovy offrent aussi concis que des notations de construction de liste, et fonctionnent bien avec Java. Étant donné que DBI encombre jusqu'au classpath, ralentit le chargement des classes un peu, et rend le code un peu plus obscure, je serais probablement de le fuir. Cependant, j'ai prévu pour ce printemps sur un ami qui venait tout juste de son SCJP et aime la bonne humeur des joutes sur la sémantique de Java! 😉 Merci à tous!

7/2017: Baeldung a un bon résumé de la double accolade de l'initialisation et le considère comme un anti-modèle.

12/2017: @Basile Bourque note que, dans le nouveau Java 9, vous pouvez dire:

Set<String> flavors = Set.of("vanilla", "strawberry", "chocolate", "butter pecan");

Qui est certainement le chemin à parcourir. Si vous êtes coincé avec une version antérieure, jetez un oeil à Google Collections ImmutableSet.

  • L'odeur de code que je vois ici, c'est que le naïf lecteur pourrait s'attendre flavors être un HashSet, mais hélas il est un anonyme sous-classe.
  • Si vous envisagez de courir à la place de la performance de chargement il n'y a pas de différence, voir ma réponse.
  • J'aime que vous avez créé un résumé, je pense que c'est un exercice intéressant pour vous d'augmenter la compréhension et de la communauté.
  • Il n'est pas obscur, à mon avis. Les lecteurs devraient savoir qu'un double ... o attendre, @ElazarLeibovich déjà dit que son commentaire. Double croisillon initialiseur lui-même n'existe pas en tant que construction du langage, c'est juste une combinaison d'un anonyme sous-classe et une instance d'initialiseur. La seule chose, c'est que les gens doivent être conscients de cela.
  • L'efficacité n'est pas la question - DBI est dangereux et source d'erreurs.
  • Belle chose que j'ai vu est le résumé; je ne vois dans aucune autre question.
  • À mon avis, double croisillon d'initialisation est une mauvaise idée.
  • Java 9 propose Immuable Ensemble Statique de l'Usine Méthodes qui peut remplacer l'utilisation de la DCI dans certaines situations: Set<String> flavors = Set.of( "vanilla" , "strawberry" , "chocolate" , "butter pecan" ) ;
  • Bourque: Oui, merci, je suis vraiment content qu'ils ont ajouté que! J'ai été en utilisant Google Collection ImmutableSet.de la(...) dans Java 8 et ne peut pas attendre jusqu'à ce que nous avons mise à niveau pour Java 9.
  • Il n'y a toujours pas de moyen facile de les initialiser une mutable collection et pas de Java 9 List.of n'est pas la même.
  • Dans Java 8, vous pouvez le faire Stream.of("vanilla", "strawberry").collect(Collectors::toSet)
  • Généralement un type particulier n'est pas importante en raison de la sous-typage.
  • le point essentiel à comprendre le code de l'odeur de ici est habituellement. Aucun avantage évident, et hideuse subtil changement de comportement.

InformationsquelleAutor Jim Ferrans | 2009-05-29