3.    Les expressions et les opérateurs


3.1    Type de résultat, transtypage.

Tous les opérateurs calculent un résultat. Quand les opérandes dans un operateur sont  de même type,  le type du résultat coïncide avec le type des opérandes (exception:le type du résultat intégral moins de 4 bytes - par exemple  byte, short  est toujours converti vers type int)

Si les  opérandes n'ont pas le même type, avant l'exécution on fait une conversion de type automatique d'un des opérandes vers le type de l'autre (si c'est possible). Si cette conversion n'est pas possible une faute de compilation est générée. Cette conversion de type porte le nom transtypage implicite (ou automatique).

Le transtypage automatique  peut s'appliquer quand il n'y a pas de risque de perte d’information.

Les six flèches noires dans la figure 3.1 indiquent les conversions sans perte d'information. Le trois flèches pointillées indiquent celles pouvant souffrir  d'une perte de précision.

            Fig. 3.1. Transtypage automatique autorisé en Java

public class Oper {
    public static void main(String arg[]){
        int k,i1=4, i2 = 5;
        double f1 =5.0,f2=5.0;
        f1= i1/i2 +i1/f2;
    }
}
•    L'expression i1/i2 se fait sans transtypage est le résultat est 0
•    Dans l'expression i1/f2, i1 est convertis en double est le résultat est 0.8
•    Le résultat final est de type double

transtypage explicite (caste)
int i = (int)56.4;            byte sh = (byte)456;

public class Oper {
    public static void main(String arg[]){
        int in;
        long ln=123L;
        double db = 34.5;
        in = ln;        //type mismatch
        in = db;        //type mismatch
        in = (int)ln;    //ok
        in = (int)db;    //ok
    }
}

public class Oper {
    public static void main(String arg[]){
        byte b1,b2=2,b3=3;
        b1 = 5;                //ok!
        b1 = b2+b3;            // type mismatch
        b1 = (byte)(b2+b3);    //ok!
        b1=130;                //type mismatch
        b1=(byte)130;        //ok!
    }
}


3.2    La priorité et l'associativité des opérateurs

Opérateurs

Associativité

()   []   .   ++(postfixé)   --(postfixé)

––>

+(unaire)   -(unaire)   ++(préfixé)   --(préfixé)   ~   !  cast new

<––

*   /  %

––>

+  -

––>

<<    >>    >>>

––>

<    <=    >    >=    instanceof

––>

==    !=

––>

&

––>

^

––>

|

––>

&&

––>

||

––>

?:

––>

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

<––


Tab. 3.1. Les opérateurs de Java et leurs priorités

3.3    Les opérateurs arithmétiques
•    +    addition;
•    -    soustraction,
•    *    multiplication,
•    /    division.

De plus, il existe un opérateur de modulo noté % qui peut porter sur des entiers ou sur des flottants. Avec des entiers, il fournit le reste de la division entière de son premier opérande par son second. Avec des flottants il fonction de la même manière mais les résultats sont approximatifs.

public class Oper {
    public static void main(String arg[]){
        System.out.println("11%4:\t"+11%4);
        System.out.println("23%6:\t"+23%6);
        System.out.println("-11%3:\t "+ -11%3);
        System.out.println("12.5%3.5:\t "+12.5%3.5);
        System.out.println("-15.2%7.5:\t "+-15.2%7.5);
    }
}

public class Oper {
    public static void main(String arg[]){
        int i= 20000000;
        System.out.println ("overloading: "+i*i);  //dépassement de capacité
        float x = 1e30f ;
        float y ;
        y = x*x ;
        System.out.println (x + " a pour carre : " + y) ;
        float zero = 0.f ; // division flottante par zero
        y=4.5f;
        float z = y/zero ;
        System.out.println (y + " divise par 0 = " + z) ;
        System.out.println("l'oppose de " + y + " = "+ -y);
        float z1 = z/y ;
        System.out.println (z + "/" + y + " = " + z1) ;
        System.out.println ("0./0.:"+zero/zero);
    }
}

·       Dans le cas des entiers,  le dépassement de capacité n’est jamais détecté. On se contente de conserver les bits les moins significatifs du résultat.

·       Dans le cas des entiers, la division par zéro (par / ou par %) conduit à une erreur d’exécution.

·       En Java, aucune opération sur les flottants ne conduit à un arrêt de l’exécution (pas même une division par zéro !). En effet, les flottants sont codés en respectant les conventions IEEE 754. Celles-ci imposent qu’il existe une valeur particulière pour représenter l’infini positif, l’infini négatif et non calculable (NaN- not a number).


opérateurs d’incrémentation (++ et --)

public class Oper {
    public static void main(String arg[]){
        int k, m=3;
        k = m++;    //m vaut 4,  k vaut 3 - valeur ancienne
        m=3;
        k = ++m;    //m vaut 4,    k vaut 4 - valeur novelle
        m=3;
        k = m--;    //m vaut 2,  k vaut 3 - valeur ancienne
        m=3;
        k = --m;    //m vaut 2,    k vaut 2 - valeur novelle   
        k= (m++)++;    //erreur!     m++ n'est pas constante
    }
}

L’opérateur d’affectation (=)

public class Oper {
    public static void main(String arg[]){
        int k, m=3,z=4,p;
        p = k =(m = 2) *(z = 4);  
                                     //m vaut 2
                                    //z vaut 4
                                    //k vaut 8
                                    //p vaut 8
        p = k = 2;                    //k vaut 2,  p vaut 2
        p = (k = 2);                //la même chose
        (p = k) = 2;                //erreur – l'opérande de gauche (p=k) est constante
    }
}

3.4    Les opérateurs de comparaisons logique

•    ==    Rend true si les deux opérandes sont égaux.
•    !=    Rend true si les deux opérandes sont différents.
•    <    Rend true si l'opérande de gauche est strictement inférieur à l'opérande de droite.
•    <=    Rend true si l'opérande de gauche est inférieur ou égal à l'opérande de droite.
•    >    Rend true si l'opérande de gauche est strictement supérieur à l'opérande de droite.
•    >=    Rend true si l'opérande de gauche est supérieur ou égal à l'opérande de droite.

public class Oper {
    public static void main(String arg[]){
        System.out.println("25>11:"+(25>11)+ "\t17<=8: "+(17<=8));
    }
}

3.5    Opérateurs logiques sur des booléens

•    &&    Opérateur ET (AND). Le résultat est true, si les deux opérandes ont la valeur true.
•    ||    Opérateur OU (OR). Le résultat est true, si l'un des deux opérandes a la valeur true.
•    !    Opérateur NON (NOT). Le résultat est true si le seul opérande a la valeur false.

public class Oper {
    public static void main(String arg[]){
        boolean b1=true,b2=true,b3=false,b4=false;
        System.out.println("true && true: "+(b1&&b2)+ "\t true && false: "+(b1&&b3));
        System.out.println("true || false: "+(b1||b3)+ "\t false || false: "+(b3&&b4));
        System.out.println("!true: "+!b1+"\t !false: "+!b3);
    }
}

3.6    Opérateurs logiques bit à bit

•    &    Opérateur ET (AND).
•    |    Opérateur OU (OR).
•    ~    Opérateur NON (NOT).
•    >>    Décalage arithmétique à droite. 
•    >>>    Décalage logique à droite. Le signe de l'opérande de gauche n'est pas gardé. On introduit toujours un zéro à gauche.
•    <<    Décalage à gauche. C'est une multiplication par 2

public class Oper {
    public static void main(String arg[]){
        System.out.println("7&8: "+(7&8)+"\t7|8: "+(7|8));
        System.out.println("~7: "+ (~7));
        System.out.println("7 << 2: "+(7 << 2));
        System.out.println("-7 >> 2: "+(-7 >> 2)+"\t -7 >>> 2: "+(-7 >>> 2));       
    }
}

3.7    Opérateur ternaire

public class Oper {
    public static void main(String arg[]){
        int res,a=4, b=9;
        res = a>b?a:b;
    }
}