hibour: j'ai dit le plus rapide dans le sens "le plus rapide à coder" pas le plus performant à l'exécution ;) Quand aux ^$ c'est une habitude :D
Version imprimable
hibour: j'ai dit le plus rapide dans le sens "le plus rapide à coder" pas le plus performant à l'exécution ;) Quand aux ^$ c'est une habitude :D
Les chiffres arabes sont ceux qu'on écrit tous :mouarf:
D'ailleurs les chiffres arabes ont été inventés en inde ;)
faut réviser tes langues, je parle bien des chiffres arabes
http://fr.wikipedia.org/wiki/Num%C3%A9ration_arabe
٠ ١ ٢ ٣ ۴ ۵ ۶ ٧ ٨ ٩
et toc :D
Ces chiffres arabes (à priori arabo-indiens) sont utilisés surtout dans les pays arabe de moyen orient (arabie saoudite, emirat arabe, liban..) et pas en maghreb qui lui utilise les nombre arabes proprement dit (0, 1, 2 ..) ;)
C'est peut-être un peu plus performant sur de très grand tableau, mais sur des tableaux plus raisonnable cela s'avère nettement moins performant !
Mais surtout ceci donne un code relativement affreux...
+1
C'est vrai qu'il y a le problème du parse() qui ne traite pas forcément toute la chaine...
Mais je voulais surtout souligné que le problème venait du fait que l'exception était ici utilisé dans un cas de terminaison normale. En effet dans ce cas précis il est tout à fait normal de passer à la méthode une chaine qui ne soit pas un nombre. Et dans ce cas on génère une exception dans un cas normal d'utilisation.
Ce n'est pas bien méchant la plupart du temps, mais en cas d'appel intensif les multiples créations d'exception peuvent s'avérer très couteuse à cause de la génération du stacktrace.
A noter tout de même que depuis Java 6 le coût de la génération du stacktrace s'est grandement réduit, et que l'impact est donc bien moins important...
a++
essaie pas de te sauver, les nombres 0 1 2 3 4 5 6 7 8 9 , appelé "nombres arabes" ne s'écrivaient pas de la même manière en arabe dès l'orginie, c'est jsute le concept et vaguement la notation qui a été piquée à l'époque, le terme correct devraient d'ailleurs etre "nombres européens" :p
Je parlais bien de la langue arabe, qui possède son propre range de caractères unicode pour les chiffres. D'facon mon collègue confirme: pour une partie des pays d'afrique du nord, c'est chiffres européens, pour une autres (tunisie, Egypte) c'est les "vrais" chiffres arabes.
Puis j'ai raison et t'as tord
Je suis maghrébin c'est pour ça j'ai insisté sur ces chiffres :lol:
Il y a un cas où on peut avoir besoin de lancer une fausse exception juste pour logger le nom de la méthode où on est
Code:
1
2
3
4
5 try { throw new Throwable(); } catch(Throwable t) { System.out.println("On est dans la méhode " + t.getStackTrace()[0].getMethodName()); }
Oui mais c'est autre chose encore puisqu'ici on a besoin des infos du stacktrace. Par contre il faut éviter de généraliser cela car cela pourrait s'avérer très couteux en fin de compte...
Au passage il n'y a pas besoin de remonter l'exception :
Mais bon cela ne change pas grand chose car tout le coût de l'opération survient lors de la création du stacktrace...Code:
1
2
3 StackTraceElement[] stack = new Throwable().getStackTrace(); // ou encore (équivalent pour le thread courant) : StackTraceElement[] stack = Thread.currentThread().getStackTrace();
a++
On ne peut pas gagner à tout les coup.. Cela m'interpelle une autre discussion où j'ai dit Généralisation VS Optimisation, Il faut trouver le bon compromis :mouarf:
Oui en effet.
Pour en revenir au sujet initial, une exception doit être fait pour remonter une erreur et non pas pour traiter un cas particulier.
Si ce n'est pas le cas il faut se poser des questions pour être sûr de ce que l'on fait.
a++
Je suis tout à fait d'accord, les exceptions sont là pour traiter des cas incohérents (business, fonctionnel).
Ne pas s'amuser à créer des millions de type d'exceptions si un type existant peut faire l'affaire.
Ne pas wrapper les exception aveuglément dans d'autres types car c'est plus difficile de retrouver ensuite la vraie raison de l'exception.
Perso je préfère wrapper une checked Exception dans un RuntimeException dans la mesure du possible (méthodes interne) pour ne pas être obligé de faire des try-catch partout :mrgreen:
Voilà mon point de vue
ca s'appelle de l'optimisation hâtive (un autre anti pattern tiens). On optimise avant de savoir où il faut optimiser. Même si ce code est un peu plus rapide que de faire un check dans le for(), il faut être réaliste. Le test sur la taille du tableau occupe une instruction CPU, alors que, rappelons le, nous avons un code dans la boucle qui appelle deux méthodes au contenu inconnu. De deux choses l'une. Soit le contenu de la boucle met du temps à s'exécuter -> alors c'est pas une lecture de propriété qui changera quoi que ce soit.
Soit le contenu de la boucle est rapide -> alors on s'en tappe, c'est pas un point chaud du code.
Pour référence, j'ai fait un code qui, 5.000.000 fois, fait le XOR de tout un tableau de 500.000.000 (500 millions d'entrées, oui) de int. Avec un boucle "classique" on se stabilise à 428ms au total, avec un boucle "exception" on se stabilise à 1776ms. Donc sur ma machine, exceptions, ca veut dire 4* plus de temps sur un boucle rapide. Si la boucle avait été lente, la différence ne se serait pas faite sentir. conclusion, on ne gagne rien avec l'exception, mais on risque de perdre.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class TestSpeed { private static final int ARR_SIZE = 500000000; static int TEST = 123456; private static void maMethode(int i){ TEST=TEST^i; } public static void main(String[] argv) { System.out.println("allocating"); int[] arr = new int[ARR_SIZE]; for (int i= 0; i< ARR_SIZE; i++){ arr[i]=i; } System.out.println("done"); for (int i=0; i< 10; i++){ long init = System.currentTimeMillis(); testSpeed(arr); long end = System.currentTimeMillis(); System.out.printf("Temps moyen pour méthode classique: %d ms\n",end-init); init = System.currentTimeMillis(); testSpeed2(arr); end = System.currentTimeMillis(); System.out.printf("Temps moyen pour méthode Exception: %d ms\n",end-init); } } private static void testSpeed2(int[] arr) { for (int i = 0; i < 5000000; i++); { int j = 0; try{ while(true){ maMethode(arr[j++]); } } catch (ArrayIndexOutOfBoundsException e){} } } private static void testSpeed(int[] arr){ for (int i = 0; i < 5000000; i++); { for (int j=0; j<arr.length;j++){ maMethode(arr[j]); } } } }
PS: on vois bien sur les premier run que le JIT essaie d'améliorer els perfs au fur et à mesure :pCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Temps moyen pour méthode classique: 488 ms Temps moyen pour méthode Exception: 2061 ms Temps moyen pour méthode classique: 463 ms Temps moyen pour méthode Exception: 1816 ms Temps moyen pour méthode classique: 427 ms Temps moyen pour méthode Exception: 1775 ms Temps moyen pour méthode classique: 427 ms Temps moyen pour méthode Exception: 1778 ms Temps moyen pour méthode classique: 427 ms Temps moyen pour méthode Exception: 1776 ms Temps moyen pour méthode classique: 424 ms Temps moyen pour méthode Exception: 1776 ms Temps moyen pour méthode classique: 426 ms Temps moyen pour méthode Exception: 1776 ms Temps moyen pour méthode classique: 425 ms Temps moyen pour méthode Exception: 1776 ms Temps moyen pour méthode classique: 426 ms Temps moyen pour méthode Exception: 1775 ms Temps moyen pour méthode classique: 423 ms Temps moyen pour méthode Exception: 1776 ms
Oui une nouvelle polémique :aie:
Encore une fois cela dépend beaucoup du contexte, mais perso j'utilise beaucoup cela pour les exceptions qui ne doivent pas arriver dans une utilisation normale de l'application.
:arrow: Cela permet d'avoir un code "fail-fast" :D
a++
Pour relancer le débat j'ai eu une idée pour les exception plus rapide si on se moque du stacktrace:
avec:Code:
1
2
3 class UntracedException extends Exception { public synchronized Throwable fillInStackTrace() { return this; } }
Je passe de environ 1300 ms à environ 300 ms, ceci dit je suppose qu'avec une trace plus compliquée à générer on doit gagner plusCode:
1
2
3
4
5
6 for (long i = 0; i < 1000000L; i++) { try { throw new /*Untraced*/Exception(); } catch (Exception e) {} }
C'est vrai que j'ai un peu trop simplifié mon exemple, mais on pourrait garder toutes les infos (sauf la stacktrace).
Si tu n'as pas besoin de la stacktrace, il y a de forte chance que les exceptions ne soient pas la solution au problème ;)
:arrow: Dans un cas d'erreur le coût de génération de la stacktrace est minime par rapport à son utilité.
a++
Bon au vu du nombre de réponses je me dis que c'était pas aussi évident que ça ....
Si on reprend l'exemple de professeur shadoko il y a en gros 2 implémentations possible que je vois :
D'après ce qui ressort de la discussion la bonne solution est la solution 2 (malgré le fait qu'il y ai redondance du test compteEnBanque.getSolde() > demandeRetrait)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 private void solution1() { // TODO Auto-generated method stub double demandeRetrait = 15; CompteEnBanque compteEnBanque = new CompteEnBanque(); try { compteEnBanque.retrait(demandeRetrait); } catch (ExceptionDepassementDecouvert e) { // TODO Auto-generated catch block log.info("Vous avez dépassé le montant du compte"); } } private void solution2() throws ExceptionDepassementDecouvert { // TODO Auto-generated method stub double demandeRetrait = 15; CompteEnBanque compteEnBanque = new CompteEnBanque(); if (compteEnBanque.getSolde() > demandeRetrait){ compteEnBanque.retrait(demandeRetrait); }else{ log.info("Vous avez dépassé le montant du compte"); } }
Vous confirmez ?