CentraleSupélecDépartement informatique
Plateau de Moulon
3 rue Joliot-Curie
F-91192 Gif-sur-Yvette cedex
Génie logiciel orienté objet - Cours : Java impératif





La syntaxe des commentaires de la forme /* ... */ vient du langage C. C++ a ajouté les commentaires lignes commençant par // (maintenant aussi autorisés an C).

L'objectif des commentaires est de faciliter la compréhension d'un programme. L'art de commenter est difficile, deux choses à retenir :

  • on suppose que le lecteur connait le langage de programmation utilisé ;
  • on peut beaucoup limiter le nombre de commentaires nécessaires en utilisant des noms de variables et de fonctions significatifs.

On notera que l'opérateur d'affectation en Java est le caractère =, comme en Python (et en C, C++…).

Pour l'explication du ; en Java, voir le transparent suivant.



Python fait partie des rares langages pour lesquels un retour à la ligne est significatif au niveau de la syntaxe. Pour la majorité des langages de programmation, un retour à la ligne est un « blanc », au même titre qu'un espace ou une tabulation, et ne sert1 qu'à séparer des éléments du langages quand c'est nécessaire.

Puisque le retour à la ligne n'est pas significatif dans la syntaxe de Java, il est nécessaire de marquer la fin d'une instruction par un autre moyen : c'est le ; qui est utilisé pour cela, il vient lui aussi du langage C.

Il n'existe pas d'opérateur d'exponentiation en Java (ni en C ou en C++), on utilise donc une fonction de la bibliothèque (Math.pow() ici).





Python impose dans un certain nombre de cas (comme ici après la condition du while, celle du if et après le else) d'utiliser le caractère : ; ce n'est pas nécessaire en Java, mais ce dernier impose par contre l'utilisation de parenthèses ( et ) autour des conditions des instructions de contrôle (c'est aussi issu du langage C).



Les caractères « blancs » n'étant pas significatifs en Java, c'est un autre solution que celle de Python qui est utilisée pour indiquer quelle sont les instructions dépendantes d'une instruction de contrôle.

En Java, par défaut, seule l'instruction suivante est dépendante d'une instruction de contrôle. Si on souhaite en mettre plusieurs (comme pour le if ici), on utilise un bloc, c'est-à-dire une suite d'instructions encadrées par { et }. Il est bien sûr possible d'utiliser un bloc même s'il n'y a qu'une seule instruction dépendante.

Ce n'est pas parce que l'indentation n'est pas significative en Java qu'il ne faut pas indenter son code afin de rendre plus visible, et donc plus compréhensive, sa structure.





Python est un langage typé dynamiquement : une variable peut être liée à n'importe quelle donnée, quel que soit son type ; c'est à l'exécution que les erreurs liées à une combinaison incorrecte de données (par exemple, diviser une chaîne de caractères par un nombre) seront détectées.

Java est lui typé statiquement : il faut préciser le type de chaque variable, le compilateur vérifie qu'une valeur affectée à une variable est compatible avec le type de celle-ci et interdit les expressions mélangeant de manière incorrecte des données.

Dans l'exemple ici, x est un entier, x1 un flottant, x2 une chaîne de caractères et x3 un booléen.



Le mot clef var utilisé ici implique un typage par inférence : c'est une forme de typage statique, mais le type de la variable est déterminé par le compilateur en fonction de la valeur d'initialisation.



Python peut manipuler des entiers de taille quelconque (sous réserve d'un espace mémoire suffisant) ; les nombres flottants sont eux représentés sur 64 bits.

Java propose plusieurs types primitifs pour manipuler des entiers (représentation en complément à 2) : les byte sont sur 8 bits, les short sur 16, les int sur 32 et les long sur 64 ; il existe aussi un type non primitif (une classe, ce concept sera expliqué dans un cours ultérieur), BigInteger, pour des entiers de taille quelconque ; pour les flottants, il existe 2 types primitifs : float sur 32 bits et double sur 64 bits.

Les littéraux entiers sont par défaut des int, le suffixe l permet d'avoir un littéral de type long.







En Python, c'est la fonction print() qui permet d'afficher des données en les convertissant en chaînes de caractères.

En Java, il faut utiliser println() (ou print() si on ne souhaite pas de retour à la ligne) — une méthode — sur out — un objet qui représente la sortie standard, votre terminal en règle générale ou la console avec Eclipse — accédé dans System — une classe — (tous ces concepts seront expliqués dans un cours à venir) pour effectuer un affichage, en utilisant la syntaxe indiquée sur le transparent.

L'opérateur +, en Python comme en Java, permet de concaténer des chaînes de caractères. Il faut par contre, en Python, explicitement convertir en chaînes de caractères les données qui ne sont pas de ce type ; en Java, la conversion est automatique.



La fonction input() de Python permet de lire des chaînes de caractères entrées par un utilisateur. Des fonctions de conversion permettent alors de convertir ces chaînes en d'autres types de données.

Il existe plusieurs façons de lire des données en Java ; la solution présentée ici est la plus simple et utilise un Scanner (System.in est un objet qui représente l'entrée standard).



Au niveau principal, un programme Python est en général composé d'un ensemble de fonctions alors que Java est composé d'un ensemble de classes (Python autorise aussi les classes).

L'équivalent d'une fonction Python est en Java une méthode statique : sans donner plus d'explications qui viendront dans un cours ultérieur, on peut dire qu'une méthode est une fonction définie à l'intérieur d'une classe (ici la fonction factorial dans la classe MathUtils), elle est qualifiée de statique de par l'utilisation du mot clef static. Notons l'utilisation du mot clef public qui sera lui aussi expliqué par la suite.

Une fonction Java (une méthode de manière générale) a, comme en Python, un nom, zéro ou plusieurs arguments et peut retourner un résultat. Par contre, Java étant typé statiquement, il faut préciser le type des arguments et celui de la valeur de retour (int pour l'unique argument et la valeur de retour dans l'exemple ici).

Notez que Java ne propose que des arguments positionnels, pas d'argument par mot-clef. On appelle signature l'ensemble constitué du nom de la fonction et du type des arguments (donc sans tenir compte du nom des arguments).



Il est possible d'écrire et d'exécuter du code Python de manière interactive, c'est aussi possible en Java avec l'outil jshell.

Quand on souhaite exécuter du code Python contenu dans un ou plusieurs fichiers, on indique sur la ligne de commande le nom du fichier qui contient le code à exécuter au départ : ce script Python peut déterminer qu'il est le script principal en testant la variable __main__.

Quand on souhaite exécuter du code Java contenu dans un ou plusieurs fichiers, on indique sur la ligne de commande le nom d'une classe, celle ci devra avoir une fonction main() ayant la signature indiquée ici. void signifie que la fonction n'a pas de valeur de retour.



Les types primitifs entiers et flottants ont déjà été présentés.

Le type booléen a comme uniques valeurs true et false.

Le type caractère permet la manipulation de caractères au standard Unicode avec le codage UTF-16 (vous pouvez ignorer ces détails techniques). Un litéral caractère est encadré par un ' (exemple : 'a') ; à noter que "a" est une chaîne de un caractère, pas un caractère.

Le type String n'est pas un type primitif (d'ailleurs, son nom commence par une majuscule). Mais vous pouvez l'utiliser sans problème pour définir des variables pouvant contenir des chaînes de caractères.



Comme Java est typé statiquement, il faut déclarer une variable (déclaration qui inclut l'information sur son type) avant de l'utiliser.

Il n'est donc pas possible de mettre n'importe quelle valeur dans n'importe quelle variable (par exemple, une chaîne de caractères dans une variable entière), l'erreur sera indiquée par le compilateur. Dans certains cas, le compilateur accepte certaines conversions (dites implicites), comme celle d'un entier vers un flottant. Dans d'autres cas, s'il y a potentiellement perte d'information, il faut utiliser une conversion explicite.



En cohérence avec le typage statique, un tableau ne contient que des éléments d'un même type, indiqué lors de la déclaration du tableau. Il faut par ailleurs le créer explicitement en utilisant le mot clef new.

Comme en python, le premier indice valide est 0, Java vérifie à l'exécution que l'indice est valide par rapport à la taille du tableau, cette taille est par ailleurs disponible via la propriété length. Il n'est pas possible de modifier la taille d'un tableau une fois qu'il a été créé (on verra plus tard un autre type qui autorise ce cas d'usage).



Une autre façon de créer un tableau est de donner ses valeurs initiales entre accolades.

Comme en Python, une variable de sorte tableau ne contient pas directement le tableau, mais un lien vers celui-ci ; comme en Python, l'affectation entre des variables de sorte tableau n'effectue donc pas une recopie des éléments : les 2 variables sont simplement liées au même tableau.





Il est possible de créer des tableaux de tableaux…

Cet exemple montre aussi que la dimension d'un tableau peut être déterminée à la compilation (exemples précédents) ou à l'exécution.



Les opérateurs en Java sont globalement identiques à ceux de Python, avec les règles classiques (par exemple, la multiplication est prioritaire sur l'addition).

Il y a cependant une différence pour les opérateurs logiques : Python utilise des mots clefs, Java les même symboles que ceux du langage C.

À noter que Java n'a qu'un seul opérateur de division : si les deux opérandes sont entiers, alors une division entière est effectuée, sinon c'est une une division flottante (avec conversion si nécessaire du second opérande entier en flottant). Si l'on souhaite effectuer une division flottante entre deux entiers, il faut donc ajouter une conversion explicite de l'un des opérandes en flottant.



Java comme Python (et comme C) offre la possibilité de combiner un opérateur arithmétique avec l'affectation.

Java (comme C) propose aussi un opérateur d'auto-incrémentation (et aussi d'auto-décrémentation : --) avec deux formes : la forme préfixée effectue l'incrémentation avant l'utilisation de la valeur, la forme postfixée après.



Une instruction conditionnelle utilise naturellement le mot-clef if (rappel : la condition doit être entre parenthèses, et il n'y a pas de :).

Il n'y a pas de mot-clef elif, on utilise donc else if.



Quand plusieurs tests successifs d'une même valeur sont nécessaires, il est possible d'utiliser une instruction switch.

Les valeurs de tests possibles sont des valeurs entières, des caractères ou des chaînes de caractères (aussi des valeurs d'une énumération, ce sera vu plus tard).

Il ne faut pas oublier le mot-clef break à la fin des instructions qui constituent un case, sinon l'exécution se poursuit au cas suivant (ce comportement est repris lui aussi du langage C).

Le cas default n'est pas obligatoire, mais doit être le dernier.



Java 14 a introduit un nouveau switch sous la forme d'une expression, c'est-à-dire conduisant à une valeur. Le break n'est ici pas nécessaire, mais il ne faut pas oublier le ; après l'accolade fermante.



Les boucles en Java sont aussi issues du langage C.

Le while n'appelle pas de remarques particulières, le do...while permet que la boucle s'effectue au moins une fois puisque la condition est testée à la fin de chaque itération.

À noter que les instructions break (sortir de la boucle courante) et continue (passer immédiatement à l'itération suivante) existent aussi en Java.



Le for est lui très général avec :

  • une instruction d'initialisation exécutée une fois au début de la boucle, qui peut contenir une déclaration de variable (on parle de variable de boucle, elle n'est plus accessible après la fin de la boucle) ;
  • une condition de continuation, évaluée au début de chaque itération ; la boucle continue si cette condition est vraie ;
  • une instruction exécutée à la fin de chaque boucle, avant l'évaluation de la condition : elle est souvent utilisée pour incrémenter un indice.













Pour avoir l'équivalent d'une variable globale (pouvant être modifiée par plusieurs fonctions), on utilisera un attribut (une variable déclarée à l'intérieur de la classe) statique.



Java impose un lien fort entre le nom d'une classe et le nom du fichier source contenant la code Java de la classe.



Ici, le fichier UneClasse.java devra être dans un dossier gloo, lui même contenu dans un dossier centralesupelec (où se trouvera le fichier Cours.java), enfin ce dernier sera dans un dossier fr.



Nous ne parlerons pas plus des modules ici. Mais comme vous allez les rencontrer avec Eclipse, ce concept est présenté brièvement.



Ce sont des conventions, donc ce n'est pas imposé par la langage. Mais il n'y a aucune raison valable de ne pas s'y conformer.



Après ce cours, vous devez faire en autonomie Mon premier programme Java avec Eclipse


 

1 Un retour à la ligne sert aussi et bien évidemment à améliorer la lisibilité d'un programme, ce qui est très important, mais non indispensable pour sa correction



© 2024 CentraleSupélec