Sommaire:
  1. String prend un S majuscule
  2. Argument de la méthode main
  3. Penser à indenter ses programmes
  4. Affectation = et opération ==
  5. Expression "==true"
  6. Quand mettre des {}
  7. La syntaxe de for
  8. Structures for et while
  9. Quand mettre "public"? Quand mettre "static"?
  10. Dimension des tableaux
  11. Fichiers .class et .java
  12. Opérations | et ||, & et &&
  13. Initialisation des tableaux
  14. Division de nombres entiers
  15. Affichage d'un tableau
  16. .length et .length()
  17. Comparaison entre String
Voici une liste des erreurs fréquentes dans la programmation en Java, qui ont été observées en TP.

  1. String prend un S majuscule
  2. De même que tous les noms de classes, et seulement ceux-là. Les noms de méthodes ou de variables ne prennent pas de majuscules. Les noms (classes ou méthodes) composés de plusieurs mots sont obtenus par juxtaposition de ces mots avec une majuscule comme premier caractéres (sauf éventuellement le premier suivant que l'on a affaire à une classe ou une méthodes). Par exemple, on peut définir une classe MaBelleClasse, une méthode maBelleMethode et une variable ma_belle_variable. Ceci n'est pas obligatoire: c'est une convention adoptée par Java. Cela permet, par exemple, de se souvenir que la classe String prend une majuscule, mais pas la méthode main.

  3. Argument de la méthode main
  4. La méthode main d'une application Java a pour argument un objet de type String []. Lorsque l'on définit une classe MonBeauProgramme dans un fichier MonBeauProgramme.java, on commence par compiler par et l'on peut le lancer par A ce moment, le "shell" d'Unix découpe cette ligne en plusieurs chaînes de caractères suivant la position des espaces (et des guillemets) et les range dans un tableau que l'on appelle souvent argv. Dans cet exemple, on a le tableau suivant Ensuite, le shell appelle le programme java et lui transmet le tableau argv. Le programme java comprend qu'il faut aller chercher la méthode main de la classe MonBeauProgramme. Il décale le tableau argv de deux crans et le transmet à main en argument. Ensuite, c'est le programme de la méthode main qui se débrouille avec le tableau de String suivant.

  5. Penser à indenter ses programmes
  6. La plupart des erreurs de programmation viennent du fait que les programmes sont peu lisibles. Augmenter leur lisibilité ne peut qu'être bénéfique. Si l'on commence un bloc d'instructions délimité par "{" et "}", on ouvre le "{" en fin de ligne de la structure qui utilise ce bloc, on indente toutes les instructions du bloc, et l'on ferme le "}" au même niveau que le début de la structure qui appelle le bloc. Par exemple, si le bloc est le corps d'une méthode: Si le bloc suit une structure if: Idem si le bloc est le corps d'une structure for.

  7. Affectation = et opération ==
  8. "n=10" est une instruction qui affecte la valeur 10 à la variable n. En revanche, "n==10" est une expression booléenne qui vaut true si la variable n est égale à 10, et false dans les autres cas. Une erreur classique consiste à écrire if(n=10) qui est incorrect. (L'erreur est notifiée par le compilateur.) La fonction if attend un argument de type booléen. Il faut donc écrire if(n==10) si l'on veut tester que n est égal à 10 ou non.

  9. Expression "==true"
  10. Dans une expression, si test est une variable de type boolean, l'expresion test==true montre que l'on n'a pas compris la notion de booléen et risque de diminuer l'appréciation d'un correcteur de pâle! En effet, l'opérateur == donne lui-même le type boolean à l'expression. Si donc test vaut true, l'expression retournera la valeur true. Si, en revanche, test vaut false, l'expression retournera la valeur false. En fait, test==(test==true) est une tautologie. Pourquoi donc utiliser une expression test==true quand on peut utiliser directement la valeur de test? On ecrira donc if(test) et non if(test==true).

  11. Quand mettre des {}
  12. Les structures if ou for acceptent une seule instruction. Leur syntaxe est Dans ce cas, soit on n'utilise effectivement qu'une seule instruction (donc sans {}) terminée par un point virgule ;, soit on utilise un bloc d'instructions qui commence par { et finit par }. Lorsqu'il n'y a qu'une instruction dans le bloc, on peut donc se passer des {}. Cette règle s'applique également aux autres structures.

  13. La syntaxe de for
  14. La structure for s'écrit inst_init, inst_trans et inst_boucle sont des instructions, et expr_test est une expression booléenne. Les délimiteurs sont ici des points-virgule ";" (et non des virgules). En général, inst_boucle est un bloc d'instructions délimité par "{" et "}". Les instructions inst_init et inst_trans peuvent être composées de plusieurs instructions séparées par des virgules. Exemple: (Noter l'emploi d'une variable booléenne on_y_va qui permet de sortir de la boucle proprement.) L'instruction inst_init est effectuée avant la boucle, le test expr_test est effectué avant toute itération (il est donc possible d'en avoir aucune), et l'instruction inst_trans est systématiquement effectuée après toute itération.

  15. Structures for et while
  16. Une des syntaxes possibles de la boucle while est On peut faire la même chose qu'une boucle for avec un while. Cependant, une boucle du genre est moins lisible que car tous les éléments importants de la boucles (initialisation, test et incrément) sont situés à des endroits différents dans la structure while. On réservera donc la structure while aux boucles qui ne sont pas itératives et dont le comportement n'est pas prévisible comme

    La structure while suivante peut être plus utile.

    En effet, dans cette structure, la condition est testée à la fin de la boucle (et non au début), si bien qu'il y a toujours au moins une itération d'effectuée. Par exemple, on peut écrire Avec l'autre type de boucle, il aurait fallu écrire et donc écrire deux fois

  17. Quand mettre "public"? Quand mettre "static"?
  18. Ce problème demande de comprendre la philosophie générale de Java en tant que langage orienté objet, ce qui n'est pas au programme du tronc commun. On utilise donc les règles simples suivantes:
    1. dans un fichier MaBelleClasse.java, on définit une et une seule classe avec public: la classe MaBelleClasse;
    2. dans la classe MaBelleClasse du fichier MaBelleClasse.java, on définit une méthode main avec public static;
    3. pour toute autre méthode que la méthode main, public est inutile;
    4. sauf si l'on définit un nouveau type d'objet, on utilise static pour toutes les méthodes et variables globales d'une même classe;
    5. si l'on cherche à définir un nouveau type d'objet (en fait, une nouvelle classe à instancier), soit on se contente des exemples donnés en cours, soit on cherche a comprendre la philosophie de Java pour savoir où utiliser static.

    Pour les curieux, on met, de manière générale, public pour rendre la classe/méthode/variable accessible depuis un autre "package". Si le programme est défini par une classe sans public, la commande Unix java que l'on utilise pour lancer l'application ne pourra pas faire référence à la classe, et donc ne pourra pas lancer le programme! De même, si cette classe MaBelleClasse est bien définie avec public, mais si sa méthode main n'est pas définie avec public, la commande java ne pourra pas faire référence à MaBelleClasse.main. Comme on ne cherche pas à référencer d'autres méthodes à l'extérieur de la classe, il n'est pas nécessaire de les déclarer publiques. De même, tant que l'on ne cherche pas à écrire plusieurs package, il n'est pas nécessaire de déclarer une classe publique.

    En plus de cette règle, le compilateur javac exige qu'il n'y ait qu'une seule classe publique dans le fichier à compiler, et que celle-ci porte le même nom que le fichier, d'où la règle 1. Moralité: n'utiliser public que pour la classe principale, et pour les méthodes devant être rendues accessibles d'une classe à une autre (règle 2).

    static signifie que l'on n'a qu'une adresse fixe et non une adresse par instanciation. Dans le cas d'une méthode, si l'on n'utilise pas static, la méthode dépend de l'instanciation de la classe: par exemple, la classe String admet une méthode

    Si l'on a un objet str de type String, celui-ci instancie la classe String, et l'on a alors accès à la méthode str.length() qui retourne un entier (qui est la longueur de la chaîne str). Les méthodes déclarées sans static s'appellent des méthodes d'instance. En revanche, si l'on utilise static pour déclarer une méthode (on les appelle des méthodes de classes), elle ne dépend plus d'une instanciation de la classe. Par exemple, la classe String admet une méthode que l'on peut appeler par String.valueOf(i). (Cela crée une chaîne qui représente l'entier i.) De même, la classe Math admet une méthode qui permet de calculer la valeur absolue de x par Math.abs(x). La classe Integer admet une méthode qui permet de décoder une chaîne str qui représente un entier en cet entier par Integer.parseInt(str).

  19. Dimension des tableaux
  20. Lorsque l'on déclare un tableau, par exemple un tableau d'entier par les éléments sont tab[0], ..., tab[99]. On peut se passer d'utiliser tab[0] en commençant à tab[1], mais ce n'est pas très élégant. En revanche, si l'on essaye d'accéder à tab[100], on aura une exception qui arrêtera le programme sur un message d'erreur. Il est recommandé de définir un tableau dont la taille correspond exactement à ce qui est utilisé pour éviter de donner l'impression que l'on ne maîtrise pas la dimension des tableaux.

  21. Fichiers .class et .java
  22. Le code source des programmes Java se situe dans un fichier dont le nom est du type MaBelleClasse.java. Ce fichier doit contenir la définition d'une classe public MaBelleClasse. On compile ce programme par qui crée un fichier MaBelleClasse.class. (D'autres fichiers .class peuvent être créés s'il y a d'autres classes définies dans le fichier.) Les fichiers .class contiennent du code dans le language de la machine virtuelle Java. Ils sont illisibles au commun des mortels. Donc, lorsque l'on transmet un programme Java, il vaut mieux envoyer le fichier source .java.

  23. Opérations | et ||, & et &&
  24. Les opérations | et || effectuent un ou logique (que l'on note OR). L'opération | prend deux entiers et effectue un OR bit-à-bit et retourne un entier. Par exemple 9|3 vaut 11 car 9 vaut 1001, 3 vaut 0011, 11 vaut 1011 et En revanche, l'opération | prend deux boolean et retourne le OR des deux. Par exemple, true || false vaut true. De même, les opérations & et && effectuent un et logique (que l'on note AND). Dans un test (par exemple, dans une structure if), il faut employer || et && (de la même manière que l'on emploie ==).

    Les opérations | et & peuvent également s'appliquer à des boolean. Il y a cependant une légère différence, car | et & évaluent systématiquement leurs deux arguments. En revanche, && par exemple n'évalue pas le second argument si le premier est false. Cela permet d'écrire (i>=0)&&(tab[i]!=0). (Avec un &, si i était négatif, l'argument tab[i]!=0 serait également évalué, ce qui conduirait à une erreur.)

  25. Initialisation des tableaux
  26. Lorsque l'on déclare un tableau par on crée un identificateur tab qui vaut null. Si l'on tente de lire à tab[4], on provoque une erreur. On doit préalablement initialiser le tableau par On effectue communément les deux instructions simultannément par la syntaxe

    Pour les tableaux a deux dimensions, on peut définir un tableau de pointeurs sur des tableaux par

    On peut l'initialiser par On peut également définir la dimension du premier tableau avant de définir celle des autres par Dans ce cas, on peut accéder au tableau tab[5] qui vaut null au départ, car il n'est pas initialisé. On l'initialise par mais cela ne préjuge en rien de tab[14]. On a ainsi tab[5].length qui vaut 50, tab.length qui vaut 100...

  27. Division de nombres entiers
  28. Lorsque l'on a trois variables a, b et c de type int et que l'on effectue on place dans c la partie entière de la division de a par b. En particulier donne le résultat 4.

  29. Affichage d'un tableau
  30. La méthode System.out.println ne permet d'afficher que des types élémentaires ou le type String. En particulier, affiche le contenu de la variable tab, soit un pointeur vers un objet composé de type "tableau d'entiers". Cela n'affiche donc pas le contenu du tableau mais une adresse mémoire qui contient le tableau.

  31. .length et .length()
  32. La longueur d'un tableau tab s'obtient par tab.length, car length est déclaré comme variable d'instance dans une classe qui représente les tableaux. En revanche, la longueur d'une chaîne de caractères str s'obtient par str.length() (avec des parenthèses vides), car length est déclaré comme méthode d'instance de la classe String, que l'on appelle donc avec une liste vide d'arguments.

  33. Comparaison entre String
  34. Si l'on a deux objets a et b de type String, il n'est pas possible de les comparer par a==b. En effet, comme String est un type composé, ses instances ne sont en fait que des références vers des cellules de mémoire, et a==b teste si l'on a la même référence et non la même chaîne. Pour les comparer, il faut utiliser a.equals(b).