5.    Les objets en Java

Java est un langage orienté objet presque pur. Un programme en Java se constitue d'un ensemble des objets qui communiquent entre eux. Les classes représentent des modèles des objets. Elles définissent leur type – les membres données et les méthodes qui déterminent le comportement de l'objet. Chaque objet est une réalisation concrète de la modèle définit par la classe correspondant. Il correspond à la notion de variable de type définit par la classe. On dit que les objets sont instances des classes.

5.1    Définition d'une classe

Le canevas général de définition d’une classe en Java est le suivant:

public class nom
{ // définition des variables membres(variables d'instances) et des méthodes de la classe
}

Exemple:

public class Person {
    public String name = "namePers";
    public int age;
    public Person(){
        name = "name1";
        age = 21;
    }
    public void growUp(int years) {
        age += years;
    }
}

La définition d'un variable d'instance contient:
•    le mode d’accès qui définit la visibilité de la variable en dehors de la classe; la visibilité sera discuté en détails un peu plus tard;
•    le type de la variable;
•    le nom de la variable.
Ces déclarations peuvent être placées où vous voulez à l’intérieur de la définition de la classe, et pas nécessairement avant les méthodes
.
La définition d’une méthode ressemble à celle d’une fonction dans les autres langages. Elle se compose d’un en-tête et d’un bloc.
L’en-tête précise :
•    le nom de la méthode – dans l'exemple growUp;
•    le mode d’accès - dans l'exemple public, visible partout;
•    les arguments qui seront fournis à la méthode lors de son appel (int years);
•    le type de la valeur de retour – void, (sans une valeur de retour).

Dans la méthode growUp la variable years désigne la valeur reçue en premier argument. La variable age désigne le champ age de l’objet de type Person qui sera effectivement concerné par l’appel de growUp.


5.2    Instance d'une classe

public class Test {
    public static void main (String[] arg){
        Person p1;
        p1 = new Person();
        Person p2 = new Person();
        p2.growUp(4);
        System.out.println("p1.age: "+p1.age);
        System.out.println("p2.age: "+p2.age);
    }
}

La classe Test possède une méthode main() qui le transforme dans une application qui pourrait être lancée On va mettre la classe Test dans le même répertoire que la classe Person. Si on lance la classe Test résultat obtenu et :
p1.age: 21
p2.age: 25

La déclaration Person p1; est différente de la déclaration d’une variable d’un type primitif (comme int n;). Elle ne réserve pas d’emplacement pour un objet de type Person, mais seulement un emplacement pour une référence à un objet de type Person. Avant de la création de l'objet cette référence est initialisée à une valeur spéciale – null. Cette valeur indique que la référence n'est pas encore liée à un objet. Si on fait une essaie de l'utiliser on obtient une erreur lors d'exécution.

Person p1;
System.out.println("p1.age: "+p1.age);        //erreur Null pointer access

L’emplacement pour l’objet sera alloué sur une demande explicite du programme, en faisant appel à un opérateur nommé new qui utilise le constructeur Person () pour donner les valeurs initiales aux variables d'instances. Ainsi, l’expression:
p1 = new Person();
crée un emplacement pour un objet de type Person et fournit sa référence en l'affectant à p1.

constructeur Person() fait l'initialisation des deux variables membres de l'objet – name et age:
name = "name1";
age = 21;




                Fig. 5.1. Référence et l'objet



5.3    Constructeurs

Un constructeur c'est une méthode spéciale, sans valeur de retour, portant le même nom que la classe. Il peut disposer d’un nombre quelconque d’arguments (éventuellement aucun). Il est utilisé avec le mot clé new pendant la création d'un objet pour donner la valeur initiale des variables membres de l'instance créée.

Person p2 = new Person();

C'est la seule méthode en Java qui ne déclare pas le type de résultat de la méthode. Même la présence de void  est une erreur.

Remarques:
•    Une classe peut ne disposer d’aucun constructeur. Dans ce cas c'est la machine virtuelle Java qui fournit un constructeur par défault qui ne fait rien. Dès qu’une classe possède au moins un constructeur (elle peut en comporter plusieurs), ce pseudo-constructeur par défaut ne peut plus être utilisé.
•    Pour pouvoir être appelé de l'extérieur le constructeur dois être déclaré public. s'il est déclaré private, la seule possibilité c'est d'être appelé par un autre constructeur.


5.4    Construction et initialisation d’un objet

Contrairement à ce qui se passe pour les variables locales, les variables membres d’un objet sont toujours initialisés par défaut.
La création d’un objet entraîne toujours, par ordre chronologique, les opérations suivante:

•    une initialisation par défaut de tous les champs de l’objet,
•    une initialisation explicite lors de la déclaration du champ,
•    l’exécution des instructions du corps du constructeur

5.4.1    Initialisation par défaut des champs d’un objet


Type de la variable

Valeur par défaut

boolean

false

char

'\u0000'

entier (byte, short, int, long)

0

float

0.f

double

0.

objet

null

Tab. 5.1 Initialisation par défaut des variables d’un objet


5.4.2    Initialisation explicite des champs d’un objet


public String name = "namePers";


5.4.3    Appel du constructeur

Leconstructeur n’est exécuté qu’après l’initialisation par défaut et l’initialisation explicite.
Les possibilités offertes par le constructeur sont beaucoup plus larges que les initialisations explicites. Sauf cas particulier, il est donc préférable d’effectuer les initialisations dans le constructeur.

5.4.4    Variables membres déclarés avec l’attribut final

public class Ex1 {
    private final int m = 10;
    public static void main(String arg[]){
        Ex1 e1,e2;
        e1=new Ex1();
        e2=new Ex1();
        System.out.println("e1.m = "+e1.m+" e2.m = "+e2.m);
    }
}
e1.m = 10     e2.m = 10


public class Ex2 {
    public Ex2(int arg) {
        m = arg ;
    }
    private final int m ;
    public static void main(String arg[]){
        Ex2 e1,e2;
        e1=new Ex2(3);
        e2=new Ex2(10);
        System.out.println("e1.m= "+e1.m+" e2.m= "+e2.m);
    }
}
e1.m=3 e2.m=10


5.5    L'accès aux membres

Aucune restriction à l'intérieur  d'une classe.

À l'extérieur - modificateurs de visibilité : public, private, protected, sans.

private String name = "namePers";
private int age;

public class Test {
    public static void main (String[] arg){
        …
        System.out.println("p1.age: "+p1.age);        //erreur de compilation
        System.out.println("p2.age: "+p2.age);         //erreur de compilation
    }
}

Les problèmes de la visibilité seront discutés plus en détails dans la section de packages de ce cours.


5.6    Membres statiques

Les variables membres et les méthodes ne sont accessibles qu'à travers l'objet particulier auquel elles sont associées. Par contre, si les membres sont déclarés avec le modificateur static, ils sont partagés par toutes les instances da la classe. Les variables déclarées avec ce modificateur sont appelées des variables statiques ou variables de classe. De même les méthodes qui sont déclarées avec le modificateur static sont appelées des méthodes statiques ou méthodes de classe.

public class Person {
    static int num=0;
    public String name;
    private int age,nm;
    public Person(){
        nm = ++num;
        name = "name"+nm;
        age = 20+nm;
    }
    public void growUp(int years) {
        age += years;
    }
    public void prt(){
        System.out.println ("name: "+name+"  age :"+age+"  number:"+nm);
    }
}
-----------------------------------------------------
public class Test {
    public static void main (String[] arg){
        Person p1;
        p1 = new Person();
        p1.prt();
        Person p2 = new Person();
        p2.prt();
        p2.growUp(4);
        System.out.println("\t\tAfter grow up");
        p2.prt();
    }
}






              Fig. 5.2 Membre statique - num



5.7    Ramasse-miettes

Il n’existe aucun opérateur permettant de détruire un objet dont on n’aurait plus besoin. La démarche employée par Java est un mécanisme de gestion automatique de la mémoire connu sous le nom de ramasse-miettes (en anglais Garbage Collector).

Lorsqu’il n’existe plus aucune référence sur un objet, on est certain que le programme ne pourra plus y accéder et l'objet est devenu candidat pour être ramassé. Le ramasse-miettes se déclenche automatiquement  quand on commence d'avoir des problèmes pour trouver assez de mémoire libre. Avant qu’un objet soit soumis au ramasse-miettes, la machine virtuelle Java essaie d'appeler la méthode finalize() de sa classe (si elle existe bien sûr).

L'exemple suivant montre comment fonctionne le ramasse-miette. La classe Garbage créée dans une boucle des objets de la classe Test et attend le démarrage du ramasse-miette. La classe Test contient quatre variables statiques:

stopNew – la valeur true arrête la création des objets de la classe Test;
startGarbage – la valeur true montre que le ramasse-miette a commence de travailler;
created – compte le nombre des objets de la classe Test déjà créés;
finalized – compte le nombre des objets de la classe Test déjà ramassés.

La première fois quand la méthode finalize() est appelée par le ramasse-miettes la création des objets est arrêté. A la fin, le programme affiche combien d'objets sont créés, quand a démarré le ramasse-miettes et combien d'objets sont ramassés



class Test {
    static boolean stopNew = false;
    static int created = 0;
    static int finalized = 0;
    static boolean startGarbage= false;     
    int num;
    Test() {
        num = ++created;
        new String("To take up space");
    }
    protected void finalize() {
        if(!startGarbage){
            System.out.println("Beginning to finalize after " + created
                    + " Tests have been created");
            startGarbage = true;
            stopNew = true;
        }
        finalized++;
        if(finalized >= created)
            System.out.println("All " + finalized + " finalized");
    }
}

//------------------------

public class Garbage {
    public static void main(String[] args) {
        while(!Test.stopNew) {
            new Test();                    
        }
        System.out.println("After all Tests have been created:\n" +
                "total created = " + Test.created +
                ", total finalized = " + Test.finalized);
        System.out.println("bye!");

    }
}





5.8    Méthodes


5.8.1    Variables locales

Allouées et initialisées explicitement  quand la méthode est appelée et détruites lorsque la méthode se termine.
Les variables locales doivent être initialisées explicitement avant d'être utilisées!

void f(){
    ...
    int var;
    if(condition){
        var= 10;
    }
    var++;            //erreur initialisation
    ...
}


5.8.2    Passage d'arguments


•    par valeur : la méthode reçoit une copie de la valeur de l’argument effectif ; elle travaille sur cette copie qu’elle peut modifier à sa guise, sans que cela n’ait d’incidence sur la valeur de l’argument effectif - types primitifs;
•    par adresse (ou par référence) : la méthode reçoit l’adresse (ou la référence) de l’argument effectif avec lequel elle travaille alors directement ; elle peut donc, le cas échéant, en modifier la valeur - objets.

class Obj {
    int i;
    Obj(){
        i=5;
    }
}
public class Test{
    public static void main(String arg[]){
        int m=4;
        Obj pr = new Obj();
        System.out.println("before: m="+m+"\t pr.i="+pr.i);
        f(m,pr);
        System.out.println("after: m="+m+"\t pr.i="+pr.i);
    }
    static void f(int k, Obj p){
        k++;
        p.i++;
    }
}

5.8.3    La référence this

Parametre invisible implicite.
 

Revenons à la déclaration de la méthode growUp:

public void growUp(int years) {
        age += years; 
}

Pour utiliser la méthode on fait un appel avec la référence d'un objet de type Person:

p2.growUp(4);

Dans la déclaration de la méthode figure un seul paramètre mais en réalité elle a deux paramètres. Le deuxième est un paramètre explicite qui est visible dans la déclaration – years. Le premier, appelé paramètre implicite est invisible. Il représente l'objet à partir du quel la méthode a été appelée (dans notre cas – p2). Cet objet peut être référencé dans le corps de la méthode par le mot clé this.  L'identificateur spécial this correspond à l'objet qui est en train d'être manipulé. Il est souvent appelé la "référence this".

La méthode growUp pourrait être écrite de la façon suivante:


public void growUp(int years) {
        this.age += years; 
}

Si une variable locale et une variable d'instance ont le même nom, la variable locale masque le nom de la variable d'instance - this devient obligatoire.

public class Person {
    String name = "namePers";
    int age;
    public Person(){
        name = "name1";
        age = 21;
    }
    public void growUp(int age) {
        this.age += age; 
    }
}



5.8.4    Méthodes statiques

Les méthodes statiques (on les appelle souvent méthodes de classe) jouent un rôle indépendant d’un quelconque objet. L’appel d’une telle méthode ne nécessite plus que le nom de la classe correspondante. Vous pouvez toujours appeler une telle méthode en la faisant lier artificiellement sur un objet de la classe (alors que la référence à un tel objet n’est pas utile).


class Stat { .....
    private double x;                            // variable usuelle
    private static int n;                            // variable de classe
    .....
    public void fu() {                            // méthode usuelle
        fs()    ;                                        // appel direct d'une méthode statique
        n = …                                        // accès direct au variable de classe
        x = …                                        // accès direct au variable usuelle
        …
    }
    public static void fs() {                        // méthode de classe
        .....                                         // on ne peut pas accéder directement à x, et à fu(). Il faut l'accéder via  une référence à objet. 
        n = …                                     // on peut accéder aux variables et aux méthodes de classe
    }
    public static void main(String[] arg) {    // méthode de classe
        Stat objStat;
        …
        fs();                                         // appel directe d'une méthode statique
        objStat.fs();                                 // reste autorisé, mais déconseillé
        objStat.x = …                            // accès au variable usuelle par un objet
        objStat.fu();                                // accès au méthode usuelle par un objet
}

Les méthodes statiques ne reçoivent pas le paramètre implicite this

5.9    Affectation et comparaison d’objets

5.9.1    Affectation d’objets

Les affectations entre les objets portent sur les références et non sur les objets eux-mêmes

class Ex{
    int x;
    int y;
    Ex(int x, int y){
        this.x=x;
        this.y = y;
    }
}
public class Affect {
    public static void main(String arg[]){
        Ex a, b;
        a= new Ex(3,5);
        b= new Ex (2,0);
        System.out.print("before assign: ");
        System.out.print ("\t a = ("+a.x+","+a.y+")");
        System.out.println ("\t b = ("+b.x+","+b.y+")");

        //assign
        a = b;
        System.out.print("after assign: ");
        System.out.print ("\t a = ("+a.x+","+a.y+")");
        System.out.println ("\t b = ("+b.x+","+b.y+")");

        //modification of a,  modify  also b :
        a.x++;
        System.out.print("after modification on a ");
        System.out.print ("\t a = ("+a.x+","+a.y+")");
        System.out.println ("\t b = ("+b.x+","+b.y+")");     
    }
}

Fig. 5.3. Les deux objets avant l'affectation



Fig. 5.4. Les deux objets après l'affectation


5.9.2    Comparaison d’objets


Les opérateurs == et != s’appliquent à des objets. Ils portent sur les références.
L’expression a == b est vraie uniquement si a et b font référence à un seul et même objet, et non pas si les valeurs des champs de a et b sont les mêmes.
Pour verifier si les valeurs des champs son les mêmes, il faut créer une méthode propre .
Toutes les classes héritent une méthode de la classe de base Objet:
public boolean equals(Object obj)
obj - the reference object with which to compare.
 
Pour les classes systèmes (par exemple String) la méthode est redéfinie correctement, mais pour les classes créées par utilisateur  elle doit être redéfinie (sinon il compare les références).

5.9.3    La notion de clone

On a besoin d'une méthode spéciale pour effectuer la recopie de tous les champs d’un objet dans un autre objet de même type. Toutefois, si les données sont convenablement encapsulées, il n’est pas possible d’y accéder directement. On doit s’appuyer sur l’existence de méthodes d’accès et d’altération de ces variables membres privés. La recopie complète d’un objet nécessiterait une bonne connaissance de son implémentation.
Dans certaines situations la copie devient une procédure récursive. La démarche la plus rationnelle pour traiter cette copie qu’on nomme clonage en Java, consiste à faire en sorte que chaque classe concernée par l’éventuelle récursivité dispose de sa propre méthode


5.10    Surcharge de méthodes

5.10.1    Définition

Surcharge (en anglais overloading) - plusieurs méthodes d'une classe peuvent porter le même nom, à condition que le nombre et le type de leurs arguments permettent au compilateur d’effectuer son choix.

5.10.2    Exemple


public class Person {
    String name;
    int age;
    Person(){
        name = "name 1";
        age = 20;
    }
    Person(String name){
        this.name=name;
        age=20;
    }
    Person(int age){
        name="name 2";
        this.age=age;
    }
    Person(String name, int age){
        this.name=name;
        this.age=age;
    }
    public static void main(String[] arg){
        Person ps[]=new Person[4];
        ps[0]= new Person();
        ps[1]= new Person(22);
        ps[2]= new Person("name 3");
        ps[3]= new Person("name 4",26);
        main(ps);
    }
    public static void main(Person[] ps){
        for(int i=0;i<ps.length;i++){
            System.out.print(ps[i].name);
            System.out.println("   age: "+ps[i].age);
        }
    }
}

5.10.3    Règles générales


Le compilateur recherche toutes les méthodes acceptables et il choisit la meilleure si elle existe. Pour qu’une méthode soit acceptable, il faut:
•    qu’elle dispose du nombre d’arguments voulus;
•    que le type de chaque argument effectif soit compatible par affectation avec le type de l’argument muet correspondant,
•    qu’elle soit accessible;
Le choix de la méthode se déroule suivant les règles:
•    Si aucune méthode n’est acceptable, il y a erreur de compilation.
•    Si une seule méthode est acceptable, elle est utilisée pour l’appel.
•    Si plusieurs méthodes sont acceptables, le compilateur essaie d’en trouver une qui soit meilleure que toutes les autres. Pour ce faire, il procède par éliminations successives.
Après élimination de toutes les méthodes possibles :
•    s’il ne reste plus qu’une seule méthode, elle est utilisée,
•    s’il n’en reste aucune, on obtient une erreur de compilation,
•    s’il en reste plusieurs, on obtient une erreur de compilation mentionnant une ambiguïté.

5.11    Les packages

Un regroupement logique sous un identificateur commun d’un ensemble de tous les classes dans une répertoire. Proche de la notion de bibliothèque. Il  permet de répartir les classes correspondantes dans différents packages. Le risque de créer deux classes de même nom se trouve alors limité aux seules classes d’un même package.

5.11.1    Utilisation


Une classe peut utiliser toutes les classes de son propre package et toutes les classes publiques des autres packages  
par le nom complet :
java.util.Date today = new java.util.Date();
java.sql.Date deadline = new java.sql.Date(1567890056871L);

ou par importer la classe spécifique :
import java.util.Date;

Date today = new Date();

Il est plus simple d'importer toutes les classes du package
import java.util.*;

Date today = new Date();

Attention pour un conflit de nom possible:
import java.util.*
import java.sql.*

Date today;                // erreur

5.11.2    Ajout d'une classe dans un package

Il faut mettre le nom du package en haut du fichier source da la classe, avant tous autre code. S'il n'y a pas une instruction package dans le fichier source, les classes dans ce fichier source appartiendront au package par défaut qui n'a pas de nom. Jusqu'à présent tous les exemples de classes se trouvaient dans le package par défaut.

Comme exemple nous allons prendre le programme du 5.10.2 mais un peu modifié et réparti en deux packages: test.first et pers.

Les fichiers doivent être mis dans le système de fichier selon le schéma suivant:



Fig.5.5 Schéma des fichiers pour les packages test.first et pers


package test.first;
import pers.*;
public class Test {
    public static void main(String[] arg){
        Person ps[]=new Person[4];
        ps[0]= new Person();
        ps[1]= new Person(22);
        ps[2]= new Person("name 3");
        ps[3]= new Person("name 4",26);
        prt(ps);

    }
    public static void prt(Person[] ps){
        for(int i=0;i<ps.length;i++){
            System.out.print(ps[i].getName());
            System.out.println("   age: "+ps[i].getAge());
        }
    }
}

package pers;
public class Person {
    private String name;
    private int age;
    public Person(){
        name = "name 1";
        age = 20;
    }
    public Person(String name){
        this.name=name;
        age=20;
    }
    public Person(int age){
        name="name 2";
        this.age=age;
    }
    public Person(String name, int age){
        this.name=name;
        this.age=age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
}

En dehors d'environnement Eclipse le lancement du programme se fait à partir du répertoire courant!

    java test.first.Test



Deux modifiers de  la visibilité au niveau de classe: public; et par défaut (sans modifier)

public class Name1{     //visible partout
   ...
}

class Name2 {             //ne visible que dans le package (le répertoire)
   ...
}

5.11.3    La visibilité des membres d'une classe


Modifier

class

package

subclass

world

public

X

X

X

X

protected

X

X

X

 

no modifier

X

X

 

 

private

X

 

 

 

Tab 5.2 La visibilité des membres d'une classe


package one;
public class Alpha {
    String name;
    public String fNumber;
    protected int age;
    private String friend;
    public Alpha(){      
    }
    public Alpha(String name,String fn,
                int age,String friend){
        this.name=name;
        fNumber=fn;
        this.age=age;
        this.friend=friend;
    }
    public String getFriend(){
        return friend;
    }
}

package one;
public class Beta {
    public static void main(String [] arg){
        Alpha alpha = new Alpha("Pijo", "1234",19,"Penda");
        System.out.println (alpha.name);
        System.out.println (alpha.fNumber);
        System.out.println (alpha.age);
        //System.out.println (alpha.friend);                            error
        System.out.println (alpha.getFriend());

    }
}

package two;
public class AlphaSub extends one.Alpha{
    AlphaSub(String name,String fn,int age,String friend){
        super(name,fn,age,friend);
    }
    public static void main(String [] arg){
        AlphaSub alpha = new AlphaSub("Pijo","1234",19,"Penda");
        //System.out.println (alpha.name);                    error
        System.out.println (alpha.fNumber);
        System.out.println (alpha.age);                        // accessible
        //System.out.println (alpha.friend);                    error
        System.out.println (alpha.getFriend());
    }
}

package two;
import one.*;
public class Gama {
    public static void main(String [] arg){
        Alpha alpha = new Alpha("Pijo","1234",19,"Penda");
        //System.out.println (alpha.name);                    error
        System.out.println (alpha.fNumber);
        //System.out.println (alpha.age);                        error
        //System.out.println (alpha.friend);                    error
        System.out.println (alpha.getFriend());
    }
}

5.12    Les classes enveloppes


type primitif

classe enveloppe

boolean

Boolean

char

Character

byte

Byte

short

Short

int

Integer

long

Long

float

Float

double

Double

void

Void

BigInteger

BigDecimal

Tab. 5.3 Classes enveloppes

Toutes les classes enveloppes disposent d’un constructeur recevant un argument d’un type primitif :
Character cObj = new Character('d');
Boolean bObj = new Boolean(true);
Float fObj = new Float(4.3f);
int m=4, n=7;
double d = 15.4;
Double dObj = new Double(fp);
Integer iObj = new Integer(m+n);

Méthode de la forme xxxValue (xxx représentant le nom du type primitif) qui permet de retrouver la valeur du type primitif correspondant :
char c = cObj.charValue;
float f = fObj.floatFalue;

emballage (boxing) et débalage (unboxing) 
Le compilateur Java effectue une conversion automatique dans les expressions entre les variables primitives et leurs wrappers d'objets correspondants. Conversion de la variable primitive vers wrapper objet s'appelle boxing, dans l'autre sens - unboxing.

Character cObj = 'd';    //boxing
Boolean bObj = true;
float fp = 15.4;
Double dObj = fp+7.3;

char c =cObj;           // unboxing
double k = dOj+7.5;

Ces classes enveloppes sont immutables : elles ne changeront pas de valeur, à chaque fois que l'on modifie un objet, Java recrée un autre objet avec la nouvelle valeur.

Trois raisons pour utiliser une classe enveloppe à la place de type primitif:
•    Pour le stockage dans les listes qui ne se fait que pour des objets.
•    Pour utiliser un constant définit dans la classe. Par exemple MIN_VALUE ou bien MAX_VALUE.
•    Pour utiliser les méthodes pour conversion des types, conversion à partir de strings, et pour conversion entre les systèmes (décimal, octal, hexadécimal, binaire).

public class WrapClass {
    public static void main(String args[]) {
        Boolean b1 = true;
        Boolean b2 = new Boolean("FALSE");
        System.out.print ("The digits in hexadecimal: ");
        for(int j=0;j<16;++j)
            System.out.print(Character.forDigit(j,16)+" ");
        System.out.println();
        int m = Integer.parseInt("254");
        int i = Integer.parseInt("ef",16);
        long ln = Long.parseLong("abcd",16);
        System.out.println(ln + " radix = 10: "+ln);
        System.out.println(ln+" radix=2: "+Long.toString(ln,2));       
        System.out.println(ln+" radix=16: "+Long.toString(ln,16));
        System.out.println("float min value: "+Float.MIN_VALUE);
        System.out.println("double max value: "+Double.MAX_VALUE);
        System.out.println("valeurs boolean: "+ b1+ "\t"+b2);
    }
}

Les objets de deux classes BigInteger et BigDecimal sont internement représentés  comme chaines de caractères. Ils n'ont pas de limite des digits, mais pour les opérations arithmétiques il faut utiliser des méthodes à la place des opérateurs:

import java.math.BigInteger;
public class Test {
    public static void main(String ar[]) {
        BigInteger bi=new BigInteger("189567432185329932"),
                bi2=new BigInteger("5");  //Initialization
        System.out.println(bi.add(bi2));     
        System.out.println(bi.multiply(bi));
    }
}


Dans l'exemple suivant on cherche de trouver le premier nombre premier (entier naturel qui admet exactement deux diviseurs distincts entiers et positifs: 1 et lui-même) qui est plus grand d'une certaine valeur. Pour le calcul on utilise la classe enveloppe BigInteger et la méthode isProbablePrime(). La vérification exacte, si un grand nombre est premier ou non, prend trop de temps. La méthode utilisée est plus rapide mais la réponse n'est pas 100% sur. Dans l'exemple l'argument de cette méthode est choisi pour que la possibilité que le nombre soit premier est évalué à 99.21875%.
import java.math.BigInteger; 
public class Big {
    public static void main(String arg[]){
        BigInteger n=new BigInteger("1000000000000");
        BigInteger one=new BigInteger("1");
        while(!n.isProbablePrime(7)) n=n.add(one);
        System.out.println("\n"+n.toString(10)+" is probably prime.");
        System.out.println("It is "+n.bitLength()+" bits in length.");}

}

5.13    La classe Math

public class MathApp {
    public static void main(String args[]) {
        System.out.println(Math.E);
        System.out.println(Math.PI);
        System.out.println(Math.abs(-1234));
        System.out.println(Math.cos(Math.PI/4));
        System.out.println(Math.sin(Math.PI/2));
        System.out.println(Math.tan(Math.PI/4));
        System.out.println(Math.log(1));
        System.out.println(Math.pow(3.1,2.2));   //puissance
        for(int i=0;i<3;++i)
            System.out.print(Math.random()+" ");  // double dans [0, 1.0)
        System.out.println();
        for(int i=0;i<3;++i)
            System.out.print((int)(Math.random()*10)+5+" ");  //entier dans [5, 15)
        System.out.println();
    }
}

5.14    Entrées/sorties sur terminal

La classe System regroupe les accès aux ressources système, fournissant des références sur la console standard via trois variables statiques – in, out et err.

variable

type

utilisée pour

in

InputStream

Lecture de l'entrée standard (la console)

out

PrintStream

Affichage sur la sortie standard (la console)

err

PrintStream

Affichage sur la sortie d'erreurs standard (la console)

           Tab. 5.4 Variables statiques de la classe System

L’affichage dans la fenêtre console se fait par l’une des fonctions System.out.println() ou System.out.print(). L'affichage des erreurs se fait par les mêmes fonctions mais en utilisant la variable statique err – System.err.println() et System.err.println().

Pour l'entrée à partir de la console on va utiliser la classe Scanner. La classe Scanner se trouve dans le package java.util et il possède des méthodes simples de lecture des variable de types primitifs de l'entrés standard (System.in)

type de résultat

méthode

Description

Scanner

new Scanner(System.in)

constructeur

BigDecimal

nextBigDecimal()

introduit l'unité suivant de type BigDecimal

BigInteger

nextBigInteger()

introduit l'unité suivant de type BigInteger

BigInteger

nextBigInteger(int radix)

introduit l'unité suivant de type BigInteger en utilisant un système de calcul de la base radix

boolean

nextBoolean()

introduit l'unité suivant de type boolean

byte

nextByte()

introduit l'unité suivant de type byte

byte

nextByte(int radix)

introduit l'unité suivant de type byte en utilisant un système de calcul de la base radix

double

nextDouble()

introduit l'unité suivant de type double

float

nextFloat()

introduit l'unité suivant de type float

int

nextInt()

introduit l'unité suivant de type int

int

nextInt(int radix)

introduit l'unité suivant de type int en utilisant un système de calcul de la base radix

String

nextLine()

introduit l'unité suivant de type String

long

nextLong

introduit l'unité suivant de type long

long

nextLong(int radix)

introduit l'unité suivant de type long en utilisant un système de calcul de la base radix

short

nextShort()

introduit l'unité suivant de type short

short

nextShort(int radix)

introduit l'unité suivant de type short en utilisant un système de calcul de la base radix

             Tab. 5.5 Méthodes utiles de la classe Scanner


import java.util.*;
public class Test{
    public static void main(String[] args)       {
        Scanner in = new Scanner(System.in);
        System.out.print("What is your name? ");
        String name = in.nextLine();                        // get first input
        System.out.print("How old are you? ");
        int age = in.nextInt();                                // get second input
        System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1)); // display on console
    }
}

Problème avec "end line"
import java.util.*;
public class Test{
    public static void main(String[] args)       {
        Scanner in = new Scanner(System.in);
        System.out.print("How old are you? ");
        int age = in.nextInt();                                // get second input
        in.nextLine();                                        //for the character "end line"
        System.out.print("What is your name? ");
        String name = in.nextLine();                        // get first input
        System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1)); // display on console
    }
}

Exemple de classe BigInteger:

import java.math.BigInteger;
import java.util.Scanner;
public class Test {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        BigInteger bi,bi2=new BigInteger("5");  //initialize bi2
        System.out.print("introduse a BigInteger\n");
        bi = in.nextBigInteger();        // read from keyboard
        System.out.println(bi.add(bi2));
        System.out.println(bi.multiply(bi));
    }

}