2009-11-20 3 views
3

Qui est moins cher et préférable: put1 ou put2?Qu'est-ce qui est préférable et moins cher: correspondance de classe vs exception?

Map<String, Animal> map = new Map<String, Animal>(); 

void put1(){ 
for (.....) 
    if (Animal.class.isAssignableFrom(item[i].getClass()) 
    map.put(key[i], item[i]); 

void put2(){ 
for (.....) 
    try{ 
    map.put(key[i], item[i]);} 
    catch (...){} 

Question révision: La question était pas claire. Permettez-moi de réviser un peu la question. J'ai oublié le casting de sorte que put2 dépend de l'échec de l'exception cast. isAssignableFrom(), isInstanceOf() et instanceof sont similaires d'un point de vue fonctionnel et entraînent donc la même dépense que l'une est une méthode d'inclusion de sous-classes, tandis que la seconde est pour la correspondance exacte et la troisième est la version opérateur. Les méthodes réflectives et les exceptions sont des opérations coûteuses.

Ma question s'adresse à ceux qui ont fait un peu de benchmarking dans ce domaine - qui est moins cher et préférable: instanceof/isassignablefrom vs cast exception?

void put1(){ 
for (.....) 
    if (Animal.class.isAssignableFrom(item[i].getClass()) 
    map.put(key[i], (Animal)item[i]); 

void put2(){ 
for (.....) 
    try{ 
    map.put(key[i], (Animal)item[i]);} 
    catch (...){} 
+1

Il semble que vous surévaluez le problème de la vitesse du processeur. Vous devriez vous préoccuper davantage de ce qu'est un code Java * correct *, clair, lisible et idiomatique. Seulement dans de rares circonstances voudriez-vous pervertir cela juste pour raser quelques cycles d'horloge. –

Répondre

12

Probablement vous voulez:

if (item[i] instanceof Animal) 
    map.put(key[i], (Animal) item[i]); 

Ceci est presque certainement beaucoup mieux que d'appeler isAssignableFrom.

ou en C# (depuis que vous avez ajouté C# tag):

var a = item[i] as Animal; 
if (a != null) 
    map[key[i]] = a; 

EDIT: La question est mise à jour qui est mieux: instanceof ou et les prises accessoires fonte. La fonctionnalité est fondamentalement la même. La différence de performance pourrait ne pas être significative et je devrais la mesurer; Généralement lancer une exception est lent, mais je ne sais pas pour le reste. Donc je déciderais en fonction du style. Dites ce que vous voulez dire.

Si vous prévoyez toujours attendre item[i] être un Animal, et vous êtes juste très prudent, coulé-et-attraper. Sinon, je trouve beaucoup plus clair d'utiliser instanceof, parce que cela dit clairement ce que vous voulez dire: "si cet objet est un animal, mettez-le dans la carte".

+1

+1 pour la deuxième suggestion - certainement la meilleure façon –

+1

Ce qui suit est également valide C# (juste pour la comparaison avec votre exemple Java: si (l'élément [i] est Animal) carte [clé [i]] = (Animal) item [i]; –

+0

Oh, et +1 btw, belle réponse :) –

2

Je suis confus. Si item[i] n'est pas un Animal, alors comment compiler map.put(key[i], item[i])? Cela dit, la première méthode dit ce que vous avez l'intention de faire, même si je crois que instanceof serait un meilleur contrôle.

1

Généralement, la gestion des exceptions sera beaucoup plus lente car, étant donné qu'elle est censée être utilisée pour des choses exceptionnelles (rarement), les fabricants de machines virtuelles ne consacrent pas beaucoup de temps à l'accélérer.

La version tr/catch de votre code que je considère comme un abus de gestion des exceptions et je n'envisagerais jamais de le faire. Le fait que vous envisagiez de faire quelque chose comme ça signifie probablement que vous avez un mauvais design, les objets devraient probablement être un Animal [] pas quelque chose d'autre, auquel cas vous n'avez pas besoin de vérifier au moment de l'exécution. Laissez le compilateur faire le travail pour vous.

1

Je suis d'accord avec une réponse précédente - cela ne compilera pas. Mais, à mon avis, qu'il s'agisse d'une exception ou d'une vérification dépend de l'objectif de la fonction.

L'élément [i] n'est-il pas un animal une erreur/un cas exceptionnel? Est-ce que cela devrait arriver rarement? Dans ce cas, cela devrait être une exception.Si cela fait partie de la logique, c'est-à-dire que vous vous attendez à ce que l'élément [i] soit composé de plusieurs choses - et seulement si c'est un animal que vous voulez placer dans une carte. Dans ce cas, la vérification de l'instance est la bonne.

MISE À JOUR: Je vais aussi ajouter un exemple (bit boiteux):

Quel est le meilleur: (1)

if (aNumber < 100) { 
processNumber(aNumber); 
} 

ou (2)

try { 
    processNumber(aNumber); //Throws exception if aNumber >= 100 
} catch() { 
} 

Cette dépend de ce que fait le programme. (1) peut être utilisé pour compter les nombres < 100 pour toute entrée entière. (2) sera utilisé si processNumber attend un pourcentage qui ne peut être supérieur à 100.

La différence est que c'est une erreur pour le programme (2) d'obtenir un nombre> 100. Cependant, pour le programme (1) aNuméro > 100 est valide, mais "quelque chose" se produit seulement quand unNumber est < 100.

PS - Cela peut ne pas vous être utile du tout, et je m'excuse si c'est le cas.

+0

Veuillez réviser votre réponse en raison de ma révision de la question. La question est instanceof/isassignablefrom vs cast exception. –

0

Vos deux alternatives ne sont pas vraiment équivalentes. Lequel choisir, dépend totalement de ce que votre code est censé faire:

  • Si l'élément devrait toujours un Animal, vous devez utiliser put2 (qui jetteront, si ce n'est pas cas ...)
  • Si l'élément peut ou ne peut pas être un Animal, vous devez utiliser put1 (qui vérifie une condition, pas une erreur ...)

Ne vous souciez jamais de la performance en premier lieu, si vous écrivez du code!

Questions connexes