next up previous contents index
suivant: 1.6 Définitions récursives monter: 1. Expressions et fonctions précédent: 1.4 Opérateurs et expressions   Table des matières   Index


1.5 Invocation d'une fonction

La seule opération que l'on peut faire sur une fonction est de l'invoquer, ou de l'appeler avec des arguments. Une invocation, ou appel de fonction, est une expression formée à partir du nom de la classe, du nom de la fonction invoquée et d'une liste d'arguments placés entre « ( » et « ) », par exemple Sommes.sommerEntiers(1,100). Si l'on invoque une fonction définie dans la même classe, il n'est pas nécessaire que le nom de la classe préfixe l'invocation. Par exemple, une invocation de la fonction sommer à l'intérieur de la classe Sommes peut s'écrire Sommes.sommer(100), ou plus simplement, sommer(100).

Rappelons la forme du programme :

package exemples;

class Sommes {

  // définition de sommerEntiers :
  static int sommerEntiers(int min, int max) { ... }

  // définition de sommer :
  static int sommer(int m) { ... }
}

class SommesTest {

  public static void main(String[] args) {
    // invocation de Sommes.sommerEntiers
    int résultat = Sommes.sommerEntiers(1, 10);
    System.out.println("Somme de 1 à 10 = " + n);
  }
}

1.5.0.0.1 Vérification des types

Le nombre des arguments (dans l'expression d'invocation) et le nombre des paramètres (dans la définition de la fonction) doivent être identiques : une invocation de sommerEntiers(1,10,100) est illégale si la fonction somme n'a pas été définie avec trois paramètres. Ensuite, le type d'un argument doit être égal au type du paramètre correspondant ou doit en être un sous-type ; par exemple, les invocations sommerEntiers("un", "dix") ou sommerEntiers(1.0, 10.0) sont illégales si la définition de sommerEntiers ne comporte pas de paramètres de type String ou de type flottant.

1.5.0.0.2 Appel ...

L'évaluation d'une invocation de fonction, de la forme C.f(arg$_1$, ...), se fait en plusieurs étapes. On représentera une invocation par le symbole $\to$ : par exemple,
SommesTest.main(...) $\to$ Sommes.sommerEntiers(1, 10)
dit que SommesTest.main(...) invoque Sommes.sommerEntiers, avec les arguments 1 et 10. Si le type d'un argument est un sous-type du type du paramètre, et si ce type est numérique, il y a promotion de la valeur de l'argument vers le type du paramètre : par exemple, l'argument $3$ sera converti en $3.0$ si le paramètre correspondant est déclaré de type double.

1.5.0.0.3 ... exécution du corps ...

Il y a alors création en mémoire d'un cadre d'invocation de la fonction invoquée, qui a pour but l'exécution du corps de cette fonction, et dont le contenu sera détaillé un peu plus loin.

1.5.0.0.4 ... et retour

Quand l'exécution du corps de la fonction invoquée est terminée, la fonction invoquée retourne. Si le type du résultat de la fonction invoquée est différent de void, la fonction retourne une valeur, qui est son résultat. La valeur retournée est celle de l'expression figurant dans l'instruction return exécutée (le corps de la fonction peut contenir plusieurs return, mais une seule sera exécutée, puisque la fonction retourne aussitôt après). Le type de cette expression doit être égal au type de retour de la fonction, ou en être un sous-type ; notamment, si ces types sont numériques, il y a promotion de la valeur de l'expression de retour vers le type de retour quand cela est possible : par exemple un « return 3; » dans une fonction déclarée retourner un double ne retournera pas l'entier $3$, mais le double $3.0$. On notera le retour d'une valeur $v$ par le symbole $\stackrel{v}{\to}$ ou par $\stackrel{v}{\gets}$ :

Sommes.sommerEntiers(1,10) $\stackrel{55}{\to}$ SommesTest.main(...),
ou
SommesTest.main(...) $\stackrel{55}{\gets}$ Sommes.sommerEntiers(1,10).
Une fonction dont le type du résultat est void retourne, mais ne retourne pas de valeur. On notera ces deux usages du verbe « retourner », intransitif en général, et transitif dans le cas d'une valeur.

1.5.0.0.5 Pendant l'invocation, la pile

Un cadre d'invocation est créé : il a une existence dans la mémoire de la Machine Virtuelle Java et une durée de vie. La zone mémoire qui lui est attribuée comporte, entre autres, les informations suivants :

Ce cadre d'invocation est placé dans une pile. La durée de vie de ce cadre est déterminée par l'exécution du corps de la fonction : il est empilé à l'invocation, c'est-à-dire placé au sommet de cette pile, et il est dépilé au retour, c'est-à-dire retiré du sommet de cette pile. Quand une fonction retourne, le cadre d'invocation qui avait été créé lors de son invocation est détruit, et les informations qu'il contenait cessent d'être utilisables. Voici le fonctionnement de cette pile, pour l'invocation de SommesTest.main() :

\begin{eqnarray*}
\begin{array}[b]{l}
\vert SommesTest.main()
\end{array}&\to
&
...
...\\
&\to
&\begin{array}[b]{l}
\vert SommesTest.main()
\end{array}\end{eqnarray*}




next up previous contents index
suivant: 1.6 Définitions récursives monter: 1. Expressions et fonctions précédent: 1.4 Opérateurs et expressions   Table des matières   Index
Rene' LALEMENT 2001-11-07