Page d'accueilFindIt !ContactObjets, tableaux et chaînesLes exceptions

Du C/C++ à JavaTM

Table des matièresHierarchie des classes

CJava

 Les instructions et les opérateurs

Les blocs
if ... else, switch
while, do ... while, for
Les expressions
Les opérateurs
Les conversions (casts)
Priorité des opérateurs

 

Les blocs

Vous allez pouvoir parcourir très rapidement ce chapitre si vous connaissez déjà le C ou le C++ : C'est surtout à ce niveau que Java et le C se ressemblent le plus car leur jeu d'instructions et d'opérateurs sont très proches.

Un bloc se note entre { } et est un ensemble de déclarations de variables locales, d'instructions (if, switch, while, do, for, try, throw, synchronized ou return), d'affectations, d'appels de méthode ou de créations d'objets dans un ordre quelconque.
A partir de Java 1.1, un bloc peut aussi déclarer n'importe où des classes internes :

{
  TypeVariable variableLocale1;
  TypeVariable variableLocale2 = valeurOuExpression;
  TypeVariable variableLocale3 [ ];
  TypeVariable variableLocale4,
               variableLocale5;
  
  //    Instructions if, switch, do, while, for, try, throw, synchronized ou return
  // ou affectations, appels de méthode ou création d'objets suivis de points virgules ;
 
  // A partir de Java 1.1 : déclaration de classes internes
}

Une instruction peut être éventuellement vide (ne rien faire) : dans ce cas, elle se note ; . Ce type d'instruction est quelques fois utilisé comme corps des instructions de boucles.
TypeVariable est soit un type primitif, soit le nom d'une classe.
A partir de Java 1.1, une variable locale ou un paramètre peut être déclaré final, pour garantir que la valeur qu'ils contiennent ne sera pas modifiée.
Une variable locale ne peut être déclarée deux fois avec le même nom à l'intérieur d'un même bloc, ni porter le même nom qu'un des paramètres d'une méthode. De plus, dans le cas d'un bloc imbriqué dans un autre, une variable locale ne peut porter le même nom qu'une autre variable déclarée dans le bloc externe.
Une variable locale (ou un paramètre d'une méthode) variable1 déclarée dans un bloc d'une classe Classe1 peut porter le même nom qu'un champ de Classe1. Dans ce cas, le champ variable1 de Classe1 est caché par la variable locale variable1. Si vous voulez faire référence au champ de la classe dans le bloc, vous pouvez utiliser l'expression Classe1.variable1, si variable1 est un champ de classe (static), ou l'expression this.variable1 si variable1 est un champ d'instance. L'utilisation de this est développée plus loin dans ce chapitre.
Toute variable locale variable1 déclarée dans une classe Classe1 peut porter le même nom qu'une méthode de Classe1 ou le même nom qu'une classe.
Une fois que le contrôle quitte un bloc, toutes les variables locales qui y ont été déclarées n'existent plus. Par conséquent, dans un bloc, la portée d'une variable locale est limitée entre le point où elle est déclarée et la fin de ce bloc.
De façon similaire, les classes internes ont la même portée que des variables locales.

C

Les variables locales en Java, sont toutes "automatiques" : Elles sont détruites une fois sorties du bloc dans lequel elles sont déclarées. Les mots clé du C auto et register n'existent pas, et static ne peut pas être utilisé pour les variables locales.

C

Les variables locales du C/C++ allouées sur la pile d'exécution de type struct, union ou class doivent être remplacées par des références qui désignent des objets créés dynamiquement avec l'opérateur new. Leur destruction se fera automatiquement non à la sortie du bloc, mais grâce à l'intervention du Garbage Collector.

C

Les variables locales peuvent être déclarées à n'importe où à l'intérieur d'un bloc, comme en C++. Si une variable locale est utilisée avant d'être initialisée, ceci provoque une erreur de compilation et pas seulement un warning comme en C/C++.

C

Contrairement au C, une variable locale déclarée dans un bloc d'une méthode methode1 () ne peut porter le même nom qu'un des paramètres de methode1 () ou qu'une des variables locales déclarées à l'extérieur de ce bloc. Les variables locales ne peuvent cacher qu'un champ de classe ou d'instance. C'est à dire l'exemple suivant provoquera des erreurs à la compilation :

class Classe1
{
  int var;
  void methode1 (int var) // Pas d'erreur
  {
    //...
    {
      int var; // Erreur : var existe déjà comme paramètre
      //...
    }
  }
 
  void methode2 ()
  {
    int var; // Pas d'erreur
    //...
    {
      int var; // Erreur : var existe déjà comme variable locale
      int var2;
      //...
    } // Après l'accolade fermante var2 n'existe plus.
    //...
    {
      int var2; // Pas d'erreur : var2 n'est pas déclarée
                // dans le bloc externe
      //...
    }
  }
}

if ... else, switch

Les instructions if et switch ont la même syntaxe qu'en C/C++, c'est-à-dire :

if (expressionBooleenne)
  instructionOuBlocSiVrai
 
if (expressionBooleenne)
  instructionOuBlocSiVrai
else
  instructionOuBlocSiFaux
 
switch (expressionEntiere)
{
  case expressionConstante1 :
    instructionOuBlocCas1
    break; // ou return; ou rien pour passer au case suivant
  case expressionConstante2 :
    instructionOuBlocCas2
    break; // ou return; ou rien pour passer au case suivant
  // ...
  default :
    instructionOuBlocParDefaut
    break; // ou return;
}

Si les expressions expressionConstantei qui suivent chaque case ne sont pas constantes, vous devez utiliser l'instruction if.

instructionOuBloc... peut éventuellement contenir les instructions return; ou return valeur; pour sortir de la méthode courante (valeur doit être du type de retour de la méthode).

C

Il existe une différence entre le C et Java pour l'instruction if (expression) : expression doit être obligatoirement du type boolean ; Donc, une condition comme if (x = y - 1) ... ne générera pas un warning (avec certains compilateurs C) mais une erreur de compilation en Java.
Cette obligation alourdit peut être l'écriture mais en améliore la lisibilité.

while, do ... while, for

Les instructions de boucles ont la même syntaxe qu'en C/C++, c'est-à-dire :

while (expressionBooleenne)
  instructionOuBloc

Tant que l'expression expressionBooleenne est true, l'instruction ou le bloc d'instruction instructionOuBloc est exécuté.

 
do
  instructionOuBloc
while (expressionBooleenne);

Comme pour l'instruction while, mais l'instruction ou le bloc d'instruction instructionOuBloc est exécuté au moins une fois, puisque expressionBooleenne est vérifiée après la première exécution de instructionOuBloc.

 
for (expressionInit; expressionBooleenne; expressionIncrementation)
  instructionOuBloc
 
for (TypeVariable variableLocale = valeurOuExpression; 
     expressionBooleenne; 
     expressionIncrementation)
  instructionOuBloc

expressionInit est exécuté puis tant que expressionBooleenne est true, l'instruction ou le bloc d'instruction instructionOuBloc puis expressionIncrementation sont exécutés.

instructionOuBloc peut éventuellement contenir les instructions suivantes :

L'équivalent de l'instruction for avec while est comme suit :

{
  expressionInit;
  while (expressionBooleenne)
  {
    instructionOuBloc;
    expressionIncrementation;
  }
}

Cette équivalence est vraie sauf si instructionOuBloc contient l'instruction continue. En effet, après l'exécution d'un continue dans instructionOuBloc, l'instruction suivante à être exécutée est l'expression expressionIncrementation de l'instruction for, tandis que pour l'instruction while c'est l'expression expressionBooleenne.

La première instruction du for expressionInit, peut comporter la déclaration de plusieurs variables du même type, séparées par des virgules (,) ; la portée de ces variables est limitée aux expressions de l'instruction for et à instructionOuBloc. La troisième instruction expressionIncrementation peut elle aussi, être un ensemble d'instructions séparées par des virgules (,), comme dans l'exemple suivant manipulant deux indices dans un même for :

class Classe1
{
  int [ ] factorielles (int max)
  {
    // Création d'un tableau de max éléments
    int [ ] tableau = new int [max];
 
    // Initialisation du tableau avec les max premières factorielles 
    for (int i = 0, fact = 1; i < max; i++, fact = fact * i)
      tableau [i] = fact;
 
    return tableau;
  }
}

C

Comme pour if, l'expression déterminant la poursuite d'une boucle while ou for doit être du type boolean.

C

for permet de déclarer une ou plusieurs variables locales, qui servent généralement d'incréments comme dans l'exemple : for (int i = 0; i < 5; i++) table [i] = 0;

Les expressions

Une expression peut prendre une des formes suivantes :

Les expression suivantes peuvent être utilisées comme expression ou comme instruction, si elles sont suivies d'un point virgule (;) :

C

Contrairement au C/C++, lors de l'appel d'une méthode en Java, les arguments sont obligatoirement évalués l'un après l'autre de gauche à droite avant d'être passés à la méthode. Ceci permet d'éviter des effets de bords imprévisibles. Par exemple, l'expression methode (i = 1, i++, ++i) sera évaluée comme methode (1, 1, 3).

C

A part les appels aux méthodes, les créations d'objet, les affectations, l'utilisation des opérateurs ++ et --, toutes les expressions Java doivent être utilisées (comme argument ou comme valeur à affecter, par exemple). Vous ne pouvez écrire val1 * val2; tout seul. Ceci permet de repérer des erreurs d'écritures du type i == 0; qui ne font rien (suite à une opération Copier/Coller trop rapide).

C

L'opérateur virgule (,) de séparation d'instructions du C, n'existe pas en Java, excepté pour éventuellement la première et la troisième instruction d'un for, et pour séparer la déclaration de plusieurs variables de même type (comme par exemple int x, y;). Vous pouvez très bien l'éviter en rassemblant les instructions dans un bloc.


Les expressions constantes utilisées après un case ou pour initialiser les constantes d'une interface, sont des expressions ne pouvant utiliser que des opérateurs arithmétiques avec des valeurs littérales ou des champs ou variables locales final initialisées avec des expressions constantes.

Utilisation de this et de super

Si dans une méthode non static methode1 () d'une classe Classe1, vous avez besoin d'une référence de l'objet sur lequel methode1 () a été invoqué, vous pouvez utiliser le mot clé this. Ceci est illustré dans l'exemple suivant :

class Classe1
{
  boolean methode1 ()
  {
    return equals (this);
  }
}
 
class Classe2
{
  void methode ()
  {
    Classe1 objet1 = new Classe1 ();
    objet1.methode1 ();
  }
}

La méthode equals () de la classe Object requiert comme paramètre une référence sur un objet. Ici, l'argument this lui est passé, qui en fait désigne objet1 (au passage le résultat est forcément true). this ne peut être utilisé que dans des méthodes non static (une méthode static n'est pas invoquée sur un objet).

C

Pour bien comprendre ce que représente this et l'appel d'une méthode sur un objet, voici un exemple de programme C (et non C++), avec une traduction possible en Java :
/* Définition d'un type de structure */
 * utilisant un int                  */
typedef struct
{
  int unEntier;
}
  Type1;
 
void modifier (Type1 *objet1, int var)
{
 
  objet1->unEntier = var;
}
 
 
 
 
/* Fonction créant un objet de type */
 * Type1 et appelant modifier ()    */
void uneMethode ()
{
  Type1 *objet1 = malloc (sizeof (Type1));
  modifier (objet1, 10);
}
// Déclaration d'une classe
// utilisant un int
class Type1
{
  int unEntier;
 
 
 
  void modifier (int var)
  {
    // this est facultatif
    this.unEntier = var;
  }
}
 
class Classe1
{
  // Méthode créant un objet de classe
  // Type1 et appelant modifier ()
  void uneMethode ()
  {
    Type1 objet1 = new Type1 ();
    objet1.modifier (10);
  }
}

A l'appel objet1.modifier (10); plusieurs opérations sont effectuées implicitement :

  1. La classe Type1 de objet1 est recherchée.
  2. La méthode modifier () de Type1 est appelée avec son argument 10.
  3. La "variable" this est initialisée avec objet1 dans la méthode modifier ().

this peut être utilisé seul pour désigner une référence d'un objet, instance de la classe Classe1 ou suivi de l'opérateur point (.) pour accéder aux champs et méthodes d'instance d'un objet. Ceci peut être utile pour distinguer un champ et un paramètre (ou une variable locale) qui ont le même nom, comme dans l'exemple suivant :

class Classe1
{
  int var;
  int var2;
 
  Classe1 (int var) // le paramètre var cache le champ var
  {
    this.var = var;
    var2 = var + 1; // équivalent à this.var2 = var + 1;
  }
}

En fait, à chaque fois que vous utilisez une méthode ou un champ non static de la classe Classe1, à l'intérieur d'une des méthodes de Classe1, vous utilisez implicitement this, mais pour des commodités d'écriture, il ne vous est requis de l'écrire que pour éviter toute confusion.

A partir de Java 1.1, une nouvelle utilisation de this a été introduite pour distinguer si besoin est, l'instance d'une classe interne ClasseI de l'instance de la classe Classe0 dans laquelle ClasseI est déclarée : ClasseI.this désigne l'instance de la classe interne ClasseI et Classe0.this désigne l'instance de la classe Classe0.

Pour référencer l'objet de la super classe de this, on utilise super. Dans la pratique, super est surtout utilisé pour invoquer explicitement la méthode outrepassée d'une super classe.
Un exemple d'utilisation de super est donné au chapitre sur la création des classes.

C

L'opérateur -> n'existe pas. Donc, comme pour toute référence en Java, this est suivi de l'opérateur point (.) pour accéder aux champs et méthodes d'instance d'un objet.

C

Contrairement au C++, this ne peut être la variable de destination d'une expression d'affectation, c'est-à-dire que par exemple, Java n'accepte pas l'expression this = unObjet.

Les opérateurs

Opérateurs arithmétiques

++, --

Opérateurs de post incrémentation et post décrémentation : variable++ ajoute 1 à variable, et renvoie la valeur de variable avant que celle-ci soit incrémentée.
variable-- retire 1 à variable, et renvoie la valeur de variable avant que celle-ci soit décrémentée.

++, --

Opérateurs de pré incrémentation et pré décrémentation : ++variable ajoute 1 à variable, et renvoie la nouvelle valeur de variable.
--variable retire 1 à variable , et renvoie la nouvelle valeur de variable.

+, -

+expression n'a aucun effet sur expression, -expression renvoie la valeur opposée de expression.

~

~expressionEntiere renvoie le complément de expressionEntiere, bit à bit. Par exemple, ~0xA7 (10100111 en binaire) est égale à 0x58 (01011000 en binaire).

!

!expressionBooleenne renvoie le complément logique de expressionBooleenne, c'est-à-dire false si expressionBooleenne est égale à true, et inversement.

*, /

expression1 * expression2 renvoie la multiplication de expression1 par expression2.
expression1 / expression2 renvoie la division de expression1 par expression2, ou déclenche une exception ArithmeticException, si expression2 est nulle et la division s'opère sur des expressions entières.

%

expression1 % expression2 renvoie le reste de la division de expression1 par expression2, ou déclenche une exception ArithmeticException, si expression2 est nulle et les expressions sont des entiers.

+, -

expression1 + expression2 renvoie l'addition de expression1 et de expression2.
Si l'un des opérandes expression1 ou expression2 est de la classe String, l'autre opérande est converti en String et le résultat est la concaténation des deux chaînes.
expression1 - expression2 renvoie la valeur de expression1 + (-expression2).

<<, >>, >>>

expressionEntiere << nbreDecalage renvoie la valeur de expressionEntiere dont les bits sont décalés à gauche, nbreDecalage fois.
expressionEntiere >> nbreDecalage renvoie la valeur de expressionEntiere dont les bits sont décalés à droite, nbreDecalage fois, avec extension du bit de signe.
expressionEntiere >>> nbreDecalage renvoie la valeur de expressionEntiere dont les bits sont décalés à droite, nbreDecalage fois, avec introduction de zéro à gauche.

<, >, <=, >=

expression1 < expression2 renvoie true si expression1 est strictement inférieure à expression2.
expression1 > expression2 renvoie true si expression1 est strictement supérieure à expression2.
expression1 <= expression2 renvoie true si expression1 est inférieure ou égale à expression2.
expression1 >= expression2 renvoie true si expression1 est supérieure ou égale à expression2.

==, !=

expression1 == expression2 renvoie true si expression1 est égale à expression2. Si expression1 et expression2 sont des références sur des objets, le résultat est true si les 2 références désignent le même objet, ou si elles sont égales à null.
expression1 != expression2 renvoie true si expression1 est différente de expression2. expression1 != expression2 est équivalent à !(expression1 == expression2).

&, ^, |

expressionEntiere1 & expressionEntiere2 renvoie le résultat d'un ET bit à bit entre les opérandes.
expressionEntiere1 ^ expressionEntiere2 renvoie le résultat d'un OU exclusif bit à bit entre les opérandes.
expressionEntiere1 | expressionEntiere2 renvoie le résultat d'un OU bit à bit entre les opérandes.
Les opérandes peuvent être éventuellement de type boolean.

&&, ||

expressionBooleenne1 && expressionBooleenne2 renvoie le résultat d'un ET logique entre les opérandes. Si expressionBooleenne1 est false alors expressionBooleenne2 n'est pas évaluée, et false est tout de suite renvoyé.
expressionBooleenne1 || expressionBooleenne2 renvoie le résultat d'un OU logique entre les opérandes. Si expressionBooleenne1 est true alors expressionBooleenne2 n'est pas évaluée, et true est tout de suite renvoyé.

? :

expressionBooleenne1 ? expression1 : expression2 renvoie la valeur de expression1 si expressionBooleenne1 est true, sinon la valeur de expression2.
x = expressionBooleenne1 ? expression1 : expression2; est équivalent à :

if (expressionBooleenne1)
  x = expression1;
else
  x = expression2;

C En Java, les opérandes de l'opérateur % peuvent être des entiers ou des nombres flottants.

C

Java a deux opérateurs de décalages à droite >> et >>>. >> recopie à gauche le bit de signe tandis que >>> introduit des zéros à gauche.

L'opérateur instanceof

L'opérateur instanceof permet de vérifier si une référence désigne un objet d'une certaine classe ou d'une certaine interface. Il s'utilise de la manière suivante : objet instanceof Classe1 et le résultat est true si objet désigne une instance de Classe1 ou des classes dérivées de Classe1 , et false sinon. Si objet est égal à null, le résultat est toujours false.
Cet opérateur est surtout utile pour évaluer la classe Classe1 d'un objet dont la référence est d'une super classe de Classe1, comme dans l'exemple suivant :

class Classe0
{  }
 
class Classe1 extends Classe0
{  }
 
class UneClasse
{
  void methode ()
  {
    Classe0 objet1 = new Classe1 ();
    Classe0 objet2 = new Classe0 ();
    Object  objet3 = new Classe0 ();
    Object  objet4 = null;
 
    boolean resultat;
    resultat = objet1 instanceof Classe1; // true
    resultat = objet1 instanceof Classe0; // true
    resultat = objet2 instanceof Classe1; // false
    resultat = objet3 instanceof Classe0; // true
    resultat = objet4 instanceof Object;  // false
  }
}

Par extension, objet instanceof Object est toujours égal à true si objet est différent de null (toute classe hérite de Object et donc tout objet est une instance d'une classe dérivée de Object).

C

Java introduit l'opérateur instanceof qui permet de vérifier si une référence désigne un objet qui est une instance d'une classe ou d'une interface donnée.

Opérateurs du C/C++ absent en Java

OPERATEUR

DESCRIPTION

->

Opérateur primaire d'accès aux pointeurs

::

Opérateur primaire d'accès aux classes

* &

Opérateurs unaires pour les pointeurs

sizeof

delete

Opérateur de destruction d'objet


Les liens définis dans le tableau désignent les endroits où il est traité de l'absence de ces opérateurs.

Les conversions (casts)

Il existe 5 contextes dans lesquels une conversion peut avoir lieu :

Conversions entre types primitifs avec gain de précision

Toutes ces conversions ne font perdre aucune précision au nombre converti. Elles ne requièrent aucun opérateur de cast, le compilateur effectue automatiquement ces conversions, mais pour clarifier votre code, vous pouvez utiliser un cast.

Conversions entre types primitifs avec perte de précision

Ces conversions ne sont autorisées par le compilateur que si le nombre à convertir est converti explicitement, grâce à l'opérateur de cast qui s'utilise ainsi : nombreType1 = (type1)nombreType2.

Conversions de références d'une classe dans une autre

Priorité des opérateurs

Tableau de précédence (priorité) des opérateurs. Les opérateurs sur une même ligne ont la même priorité, et sont rangés ligne par ligne du plus prioritaire au moins prioritaire.

OPERATEUR

ASSOCIATIVITE

DESCRIPTION

. ( ) [ ] new

de gauche à droite

Opérateurs primaires

! ~ ++ -- + - (cast)

de droite à gauche

Opérateurs unaires

* / %

de gauche à droite

Multiplication, division, reste

+ -

de gauche à droite

Addition, soustraction

<< >> >>>

de gauche à droite

Décalages

< <= > >= instanceof

de gauche à droite

Comparaisons

== !=

de gauche à droite

Egalité, différence

&

de gauche à droite

Opérateur ET bit à bit

^

de gauche à droite

Opérateur OU EXCLUSIF bit à bit

|

de gauche à droite

Opérateur OU bit à bit

&&

de gauche à droite

Opérateur ET

||

de gauche à droite

Opérateur OU

? :

de gauche à droite

Condition

= *= /= %= += -= <<= >>= >>>= &= ^= |=

de droite à gauche

Affectation

L'opérateur new a la même priorité que l'opérateur . , ce qui permet d'écrire directement new Classe1 ().methode1 (). En C++, il faut écrire (new Classe1 ())->methode1 ().


Page d'accueilFindIt !ContactObjets, tableaux et chaînesLes exceptionsDébut de la page
© Copyrights 1997-2023 Emmanuel PUYBARET / eTeks
- Tous droits réservés -
Table des matièresHiérarchie des classes