2009-03-22 2 views
4

Ceci est une question sur le code Java, tels que:conséquences non intentionnelles de la classe anonyme créé juste pour l'amour d'ajouter par exemple le bloc d'initialisation

List<String> list = new ArrayList<String>() {{add("hello"); add("goodbye");}} 

où le programmeur a étendu ArrayList anonyme juste pour le plaisir de bousculade dans une instance bloc d'initialisation.

La question est: si la seule intention du programmeur est simplement d'obtenir la même chose que:

List<String> list = new ArrayList<String>(); 
list.add("hello"); 
list.add("goodbye");  

alors quelles sont les conséquences inattendues de ce fait la première manière?

Répondre

15

Le danger de faire ce genre de code (dans le cas général) est que vous pourriez casser equals() méthodes. C'est parce qu'il ya deux modèles généraux pour equals():

public boolean equals(Object ob) { 
    if (!(ob instanceof MyClass)) return false; 
    ... 
} 

et

public boolean equals(Object ob) { 
    if (ob.getClass() != getClass()) return false; 
    ... 
} 

La première sera toujours travailler avec les sous-classes anonymes dont vous parlez, mais le second ne sera pas. Chose est, la seconde est considérée comme la meilleure pratique parce que instanceof n'est pas nécessairement commutatif (ce qui signifie a.equals(b) pourrait ne pas être b.equals(a)).

Plus précisément dans ce cas cependant ArrayList utilise la méthode AbstractList.equals() qui vérifie simplement que l'autre objet est un instanceof l'interface List, vous êtes très bien.

Cependant, il faut en tenir compte.

Ce que je suggère est de le faire un peu différemment:

List<String> list = new ArrayList<String>(
    Arrays.asList("hello", "goodbye") 
); 

Bien sûr, il est plus verbeux, mais vous êtes moins susceptibles d'avoir des ennuis ainsi que la classe résultante est un « pur » ArrayList.

+0

Bonne réponse, bien placé. – mafu

0

La première approche est également mauvaise pour les performances. L'encombrement de la mémoire avec beaucoup de classes anonymes n'est pas bon. En outre, il sera plus lent au démarrage.

+0

Je ne suis pas d'accord avec cela. Le premier et le second cas effectueront exactement la même chose. Cependant, le premier cas est mauvais à cause de ce que le cletus a très bien expliqué. – LordOfThePigs

+0

Une fraction de milliseconde de performances de démarrage et environ 2 000 heap persistant (par utilisation). –

5

Je pense que le gros problème ici est que vous créez une classe interne de la classe environnante. La liste que vous créez aura une référence implicite cette référence à la classe externe.

Ce n'est normalement pas un problème. Cependant, si vous sérialisiez cet objet (je pense en particulier à utiliser XStream depuis que je l'ai moi-même rencontré), alors le formulaire sérialisé contiendra la classe externe sérialisée. Ce qui n'est pas du tout ce que vous attendez normalement et peut entraîner un comportement particulier!

J'utilise beaucoup le modèle d'initialisation ci-dessus. Tant que vous connaissez le mécanisme de la classe interne, ce n'est pas un problème. btw. Je ne pense pas que la question de l'égalité soit un problème au-delà de celui des implémentations d'égalité sur les dérivations en général.

+0

+1 C'est un excellent point sur l'implicite de cette référence. – cletus

+0

Habituellement, vous faites cela à partir d'un contexte statique, ou vous vous en fichez (dans un test, par exemple). Si c'est le cas, disons, que la nouvelle ArrayList <.>() fera l'affaire. L'utilisation de Arrays.asList peut réduire la charge de mémoire. –

2

L'impact sur les performances du code et/ou de la mémoire est négligeable (si mesurable).

Le vrai coup ici est que vous faites que les gens s'arrêtent, même pour un battement, pour penser "qu'est-ce que ce mec fait?"

Si je dois faire cela 1000 fois pendant que je lis votre code, il y a le problème de performance.

Le code devrait être facile à lire - tant que toutes les exigences de performance, d'exhaustivité et de normes sont respectées.

Très probablement, vous allez être la personne qui maintient votre code. Soyez gentil avec votre avenir et faites en sorte que le code soit FACILE A LIRE. Si vous voulez faire quelque chose de fantaisiste comme ça, ayez une bonne raison et documentez-le dans le code. Si la seule raison est de montrer vos talents en tant que programmeur, vous avez échoué dans le vrai travail d'un programmeur: rendre le difficile facile.

+0

Vous devez penser la première fois que vous voyez l'idiome - alors c'est fait. Beaucoup plus facile à lire ce code, IMO. –

+0

@Tom Vous avez tort. La deuxième façon est standard, donc mieux vaut l'utiliser. La première façon est le matériel DailyWTF. – starblue

Questions connexes