Pierre Schambacher.com
Ingénieur en Informatique pour Intellicore

fév/10

28

Java c’est nul !

Aujourd’hui c’est coup de gueule ! Je sors de ma longue torpeur pour gueuler un coup, JAVA C’EST NUL ! http://cestnul.fr/Java

Etant donné que je ne suis pas homme à gueuler sans preuve, voici la démonstration de ce que j’avance.

Java Fail

Je vous laisse le temps de lire ce petit bout de code et deviner le résultat logique d’une exécution…
Si vous pensez comme moi, vous vous attendez à ce résultat:

Object: java.lang.String
Integer
Float

Réfléchissons deux minutes.

Nous avons une liste qui contient différents objets, une chaîne de caractère, un entier et un nombre décimal. Notre classe Main présente une méthode polymorphique prenant en paramètre un Object, un Integer ou un Float.
Pour le premier objet la méthode la plus approchante est la méthode avec le paramètre Object.
Pour les deux autres la méthode avec le paramètre de type exact va être appelé du fait que la liaison en java est dynamique et décidée à l’exécution. Le fameux « VIRTUAL » des programmeurs C++.

Voyons le résultat de l’exécution (JVM 1.6 sur MacOS 10.6 dit « Snow Leopard »):

Object: java.lang.String
Object: java.lang.Integer
Object: java.lang.Float

Mais ????!!!! Voilà un résultat qui ferait lacher à nos amis anglo-saxons un virulent « WTF ?! ». Que c’est-il passé ?

Et bien c’est extrêmement facile. Nous nous trouvons devant un manique échec de Java et ses méthodes liées à l’exécution… Le compilateur voit que l’ArrayList contient des instances de Object, il voit une méthode prenant en paramètre un Object, il fait la liaison à la compilation. Dans le langage courant on dirait simplement: JAVA FAIL !

Si vous ne me croyez pas, vous pouvez simplement télécharger le fichier de test ici (en renommant le fichier Main.java évidemment). Pour le principe j’ai changé Object en Number (superclasse de Integer, Float, Double, …) et le résultat est bien sûr le même, comme vous le constaterez .

RSS Feed

10 commentaires pour Java c’est nul !

Sébastien Mosser | 28 février 2010 à 7:33

Bon, je te rejoint sur le fait que « oui, Java, c’est nul », et pour pleins de raisons … mais je ne comprend pas celle que tu invoque …

Le comportement que tu donne est « juste » complètement normal … Les classes « Integer » et « Float » appartiennent à java.lang, et il te les affichent avec leur nom qualifié pour éviter toute ambiguïté …

Et même si tes paramètres était typé avec des scalaires (‘int’ et ‘float’), le boxing aurait produit un résultat comme celui-là … à moins que ce ne soit qu’en C# et que Java ne l’ai pas encore pompé … oops, mémoire défaillant …

Commentaire de l'auteur: Pierre Schambacher | 28 février 2010 à 7:48

Le problème est qu’en affichant « Object: java.lang.Integer » au lieu de « Integer » (notes l’absence de Object) je monte qu’il passe par la méthode trace(Object) et non pas par la méthode trace(Integer) ou trace(Float) qui est le comportement que j’attendais. J’ai ajouté le getClass().getName() pour éviter qu’on me dise qu’il s’agit « peut-être » d’un autre type que Integer ou Float.

Le fait est que la liaison est faite de façon statique, et non pas dynamique comme on nous le vend. Si c’était le cas il verrait à l’exécution que l’objet est un Integer, et appellerait la méthode avec la signature la plus proche du type voulu. J’ai découvert ce comportement avec un code très différent (impliquant des NSArray, NSMutableDictionnary et autres joyeusetés) mais le résultat est le même: si tu passes un Object en paramètre, il link l’appel à la méthode Object sans chercher à savoir si à l’exécution une autre méthode collerait mieux.

y!onel | 28 février 2010 à 9:45

Hum hum, d’abord, non ! java n’est pas nul ;)
Pour m’être aussi mangé les dents là dessus, il ne faut pas confondre le polymorphisme, dynamique, qui s’applique aux objets sur lequels on appelle les méthodes, et le choix des méthodes en fonction des types de paramètres, qui est lui statique.
Le polymorphisme ne s’applique pas aux paramètres.
Je suis quasiment sûr que tu aurais le même problème en C++
Par contre si dans ton code, au lieu de main.trace(o) tu fais o.toString(), tu ferais appel réellement dans ce cas au polymorphisme, dynamique, qui trouverait la bonne méthode toString() en fonction du type de o , au runtime.

Commentaire de l'auteur: Pierre Schambacher | 28 février 2010 à 10:07

Huhum … voilà qui explique tout.
Toutefois bien que le comportement est expliqué, il n’en reste pas moins peu pratique !! J’aimerais bien avoir le retour de programmeurs C++, C#, … sur un test comme ça voir si l’un d’entre eux se comporte comme je m’y attendais.
Puis-je compter sur toi pour tester l’Objectif C ? ;-)

PS: si Java c’est nul !! Mais j’ai assez grogné pour aujourd’hui, je ferais un autre billet pour me défouler une autre fois.

y!onel | 28 février 2010 à 10:12

Je pense qu’en objectiveC c’est pareil :) Mais je ferai le test pour vérifier :)
OK, j’attends le prochain post sur la nullité de Java pour affuter de nouveaux contre-arguments ! :p

y!onel | 1 mars 2010 à 9:04

La nuit porte conseil : en fait en objectiveC c’est pas pareil : le choix d’une méthode ne se fait pas suivant les types. En gros déclarer des méthodes de même noms, mais avec des types différents en paramètre:
-(void) maMethode:(type1)var1
et
-(void) maMethode:(type2)var2

conduirait à une ambiguité, le compilo signalerait une erreur.
C’est pour ça qu’on souvent des noms de méthodes qui typent par leur nom :
-(void) maMethodeAvecType1:(type1)var1
et
-(void) maMethodeAvecType2:(type2)var2

Alors nul / pas nul ? ;) je te laisse juge, au moins ça a le mérite d’être clair et d’éviter une potentielle incompréhention :)

Commentaire de l'auteur: Pierre Schambacher | 1 mars 2010 à 10:13

Mes collègues de boulot m’ont répondu pareil.
Je trouve ça un peu gênant car on aboutit à un résultat semblable qu’avec Java: un gros paquet de tests sur le type de l’objet. Cependant si j’avais à faire ça en Objectif C je passerais par une catégorie et contournerait ainsi le problème. Impossible de le faire en Java ^

Sébastien Mosser | 1 mars 2010 à 10:21

Ok, j’avais lu en diagonale ton post. Mais du coup, c’est pas « juste » parce que tu essaye d’avoir du polymorphisme sur tes paramètres?

La liaison dynamique en java se fait a la réception de message (=> quand ton instance de Main reçoit le message ‘trace’). Gait un google sur ‘late binding’, tu verras que c’est complètement normal … :)

Sébastien Mosser | 1 mars 2010 à 10:21

en plus, j’ai répondu sans lire les autres commentaires (j’accumule …). Désolé du doublon ;) .

Java Evangelist | 30 avril 2010 à 11:44

Pierre Schambacher,

Java n’est pas nul, mais c’est toi qui es nul.

Laissez un commentaire!

<<

>>

Recherche!

Theme créé par devolux.org personnalisé par Pierre Schambacher