Sauf pour le cas déjà mentionné des questions concernant le bon style de programmation et l'héritage de l'abus, il y a un problème plus subtil - les classes internes (non statique) anonyme des instances de classe loi que les fermetures. Cela signifie qu'ils garder une référence implicite à l'instance de la classe englobante. Cela peut entraîner dans la prévention de la collecte des ordures et à la fin, une fuite de mémoire.
Étant donné un exemple de morceau de code source:
public interface Inner {
void innerAction();
}
public class Outer {
public void methodInOuter() {}
private Inner inner = new Inner() {
public void innerAction() {
// calling a method outside of scope of this anonymous class
methodInOuter();
}
}
}
Ce qui se passe au moment de la compilation, le compilateur crée un fichier de classe pour la nouvelle anonyme sous-classe de la Inner
qui reçoit un soi-disant terrain synthétique avec la référence à l'instance de l' Outer
classe. Le bytecode généré sera à peu près équivalent à quelque chose comme ceci:
public class Outer$1 implements Inner {
private final Outer outer; // synthetic reference to enclosing instance
public Outer$1(Outer outer) {
this.outer = outer;
}
public void innerAction() {
// the method outside of scope is called through the reference to Outer
outer.methodInOuter();
}
}
Une telle capture de référence pour l'affichage de l'instance qui se passe, même pour les classes qui ne sont jamais vraiment accéder à des méthodes ou à des champs de la classe englobante, comme le double-brace initialisé (DBI) de la liste dans votre question.
De ce fait, que le DBI liste conserve une référence à l'instance englobante aussi longtemps qu'elle existe, la prévention de la enfermant instance d'être nettoyée. Supposons que le DBI liste arrive à vivre pour une longue période dans l'application, par exemple en tant que partie du modèle dans le modèle MVC, et la capture de classe englobante est par exemple un JFrame
, ce qui est une assez grande classe avec beaucoup de champs. Si vous avez créé un couple de DBI listes, vous obtiendrez une fuite de mémoire très rapidement.
Une solution possible serait d'utiliser DBI seulement en statique méthodes, car il n'y a pas une telle instance englobante disponibles dans leur champ d'application.
D'autre part, j'ai toujours fait valoir que l'utilisation DBI est toujours pas nécessaire dans la plupart des cas. Comme pour la liste de rejoindre, je voudrais créer un simple réutilisables méthode, qui est non seulement plus sûre, mais aussi plus concis et clair.
public static <T> List<T> join(List<? extends T> first, List<? extends T> second) {
List<T> joined = new ArrayList<>();
joined.addAll(first);
joined.addAll(second);
return joined;
}
Et puis le code du client devient simplement:
List<String> newList = join(listOne, listTwo);
Pour en savoir plus:
http://stackoverflow.com/a/924536/1064809