Vous êtes sur la page 1sur 80

1.

If

Grammaire :

If Then Statement :

if (Expression) Statement

Remarque : L'expression doit obligatoirement être entre parenthèse et être de


type booléene, sinon, erreur de compilation. Si c'est une instruction vide alors il ne se
passe rien dans le if.

Il est executé après avoir testé l'expression, si elle est vraie, il execute
l'instruction (Statement), sinon, il ne l'execute pas.

If Then Else Statement

if (Expression) StatementNoShortIf else Statement

Il est executé après avoir testé l'expression, si elle est vraie alors on execute le
bloc d'instrcutions qui suis le if, si cette expression est fausse, on execute l'instruction
qui suis le else.

Le if détermine le « si » en algorithmique, tandis que le else lui exprime le « sinon »


vu en algorithmique. A noter que le else ne peut exister sans le if. Le if est utilisé dans
le cadre des alternatives. C'est un mot clé (tout comme else)

Les accolades sont optionnelles, si on ne les met pas, ça compile quand même et les
instruction sont executé. On met donc les accolades par convention mais pas
seulement, en effet, quand on execute plus d'une instruction et qu'on omet les
accolades, seule la première instruction est considérée dans le if, ce qui n'est pas le
cas lorsqu'on les utilise afin de rassembler en bloc d'instruction.

Le principe du dangling else consiste a dire que le else appartiens au if qui le précède,
en effet, si on ne met pas les accolades, et qu'il y'a une succession de if, on ne sais pas
auquel appartiens le else. C'est l'une des raison pour lesquels on pensera a utiliser les
accolades pour contourner le problème.

L'expression booléene dont on traite dans la grammaire peut être de différentes


formes :

- un opérande unaire comme une négation (!) ou une variable.


- un opérande ternaire comme ?
- les comparateurs ( <, > ≥= , ≤=,!=)
- le true et le false, classique
- un appel de méthode qui renvoie un booleen
- une variable booléene
- les opérateur logique ||, &&.

Il est important de savoir que le if-else simple avec une instruction peut être remplacé
par un opérateur ternaire ?.

Exemple : String salutation = (heure > 12) ? « Bonjour » : « Bonsoir»

Le premier choix sera effectué si la condition est vraie, sinon il ne sera pas
effectué.

exemples de If :

1// if ( i == 2) {
i=6;
}

2// if (!n) {}

3// if (i == 3) {
i=4;
} else {
i=5;
}

4// if (i==1)
i=2 ;
else
i=3;
2. Expression Booléene

Une expression est composée d'opérateur, de variable, d'appel de méthode ou


d'opérande. Pour une expression booléene, la valeur sera soit true, soit false.

Les expression booléenes peuvent être écris via des opérateur* uniaire ( ! ou
variable), binaire (==, <, >, ≤, ≥ ,!=), ternaire (?)* via les valeurs true ou false, via des
appel de méthode qui renvoient un booléen ou encore via des variables booléenes.

* A noter qu'un opérateur a toujours besoin de 1, 2 ou 3 opérandes en fonction du


faire qu'il soit unaire, binaire ou ternaire.

Le séparateur permet de séparer l'expression booléene du reste de l'instruction. Il peut


être (), [] ou encore {}.

exemple :

if (a>b) {
i=1;
}

3. Visibilité

Private

La visibilité private s'applique à un champ (attribut ou méthode) d'une classe, il n'est


pas accessible en dehors de cette même classe, sauf via un accesseur (getter) ou un
mutateur (setter).

Exemples :

un attribut nombre déclaré comme ceci :

private int nombre;

pour y acceder les méthodes dans la classe en question sont public :

public int getNombre() {


return nombre;
}

public void getNombre(int nombre) {


this.nombre = nombre;
}
Public

La visibilité public permet d'acceder aux champs à partir de toute les autres classe, on
peut tout y modifier et y acceder comme on veut.

Pour y acceder on utilise nomDeLaClasse.nomChampPublic

par exemple si je veux acceder a l'attribut suivant dans la classe Projet:

public int nombre;

je pourrait y acceder via Projet.nombre et même le modifier.

Protected (fait référence a l'héritage)

La visibilité protected est utilisée lorsqu'on veut que les attribut et les méthodes de la
classe mère soit visible dans la classe fille. Du coup, au lieu de mettre le champ
comme étant private dans la classe mère, on le met protected.

Exemple :

public class Employé {


protected String nom;
protected String prénom;
protected int matricule;
protected int salaire;
}

lorsqu'on utilisera le mot clé extends, les attribut de la classe mère seront accessible
pour la classe fille et elle va donc pouvoir en hériter comme si ils étaient en private

public class Manager extends Employé {


private int prime;
}

la classe Manager aura donc également les méthode et les attribut déclaré en
protected dans la classe mère.

Package (absence de mot-clé)

Cette visibilité apparaît lorsque les champ sont accessible depuis toute les classe du
même package. Pour la définir, on ne met aucun mot clé de visibilité.
Exemple :

boolean isFree(Position position)


int package

Si la classe qui contiens les attributs déclaré comme package est dans le package
esi.util alors toute les classe qui se trouvent dans esi.util y auront accès.

4.Switch

Grammaire :

Switch Statement :

switch (Expression)* SwitchBlock

SwitchBlock :

{ {SwitchBlockStatementGroup} {SwitchLabel} }

SwitchBlockStatementGroup

SwitchLabel BlockStatement

BlockStatement c'est le bloc d'instruction

SwitchLabel

case ConstantExpression:
case EnumConstantName :

ConstantExpression c'est les nombres,comme 2,3,4, leur valeur reste la même mais
également les String etc...

EnumConstantName :

Identifier

C'est l'une des valeur que l'énumération peut prendre.


AssignementExpression

LeftHandSide AssignmentOperator Expression

Le LeftHandSide c'est le nom de la variable à laquelle on assigne quelque chose.

L'AssignmentOperator c'est l'opérateur qui donne une valeur à la variable. ( =, +=, -=


etc..)

l'expression est une ConstantExpression.

Exemple//

int var;

switch (var = clavier.nextInt()) {


case 3 :
system.out.println(« fayen a fou ») ;
break ;
case 4 :
system.out.println (« bien ou bien ? ») ;
break ;
default :
}

Le switch peut contenir des byte, char, short, int (ainsi que leur type référence Integer,
Character, Short etc..) ,des String et des énumération.

Attention, le switch ne peut PAS contenir de boolean ou double (ainsi que leur type
référence)

On utilise le mot clé break pour sortir du switch. Il est généralement placé a la fin du
case pour accomplir les instruction avant de quitter le switch, mais ça n'est pas
obligatoire, par contre si on oublie le break a la fin de notre case, tout les autres cas
qui le suivent seront également executé. C'est également la cause pour laquelle on ne
met pas de break a la fin du default car il est en général placé a la fin du switch.

Le mot cle default sers à exécuter un bloc d'instruction si aucun case ne correspond à
la valeur que la variable a prise. Ce mot clé est optionnel, on peut ne pas le mettre.
Exemple (avec énumération)

switch (Saison) {
case PRINTEMPS :
case ETE:
system.out.println(« En » + Saison + « Il fait beau ») ;
break;
case AUTOMNE :
case HIVER :
system.out.println(« En » + Saison + « Il fait froid ») ;
}

On remarque qu'il n'y a pas de break a la fin car on quitte le switch, mais on a du
mettre un break pour les cas PRINTEMPS et ETE afin de quitter le switch une fois
que l'instruction est exécutée.

Le switch équivaut au « selon que avec valeur » en algorithmique. L'autre « selon


que » est le « selon que condition » et peut être assimilé a une série de if-else
imbriqués car le switch ne permet pas de le reproduire.

Exemple selon que condition

if (i==1) {
//instruction
} else if (i < 1) {
//instruction
} else if (i> 1) {
//instruction
}
5. Import

On utilise le mot clé import lorsqu'on veut utiliser une classe qui se trouve dans un
autre package.

Ex : import monPackage.maClasse ;

Pour faire l'appel d'une méthode dans ce cas là, on mentionne le nom de la classe
ainsi que la méthode. Par exemple Math.PI

Une fois que l'import est fait on peut utiliser nomClasse sans mentionner le nom de
son package. On peut également importer toute les classe d'un package en utilisant le
joker * qui permet donc d'importer toute les classe du package cité précédemment.

Ex : import monPackage.esi.* ; → importera toute les classes du package


monPackage.esi

L'utilisation de import static * permet d'importer toute les méthode d'une classe et de
pouvoir les utiliser sans devoir citer le nom de la classe.

Ex : avec import static java.lang.Math.* → pour utiliser la racine carré on utilise


simplement sqrt().
On doit obligatoirement mettre le nom d'un package lorsqu'on importe, sinon ça ne
fonctionne pas.

Ex : import * ; → ne compilera pas.


6. Break/Continue

Break

Le break permet d'arrêter une instruction.. On l'utilise dans les switch, les for, les
while ou les do-while.

Grammaire
BreakStatement
break Identifier(opt) ;

L'identifier est optionnel car si on ne le met pas, il arrête l'instruction en cours.


Si on met l'identifier il arrête le label qui est trouvé en remontant le code, cette
utilisation peut-être intéressante lorsqu'on veut arrêter des boucle imbriquée

ex :

while {
for(…) {
break ;
}
//on se trouve ici après le break
}

dance : while {
for(…) {
break dance ;
}
}
// après le break on se trouve là

Continue

Grammaire
ContinueStatement
continue Identifier(opt)

Le continue est utilisé dans le cas d'une boucle (for et while) et d'un arrêt
inconditionnel. Si il n'y a pas de label il réitère l'instruction en cours, si il y'en a un, il
réitérer l'instruction étiquetée par le label.
Exemple :

int x = 1
for (int x = 0 ; x<= 10 ; x++) {
if (x == 7) {
system.out.println(« division par zéro ») ;
continue ;// quand on arrive a x=7 il n'effectue pas le calcul et passe au
suivant
}
double a = 1*6/(x-7) ;
system.out.println (a);
}

7. Static

static est un mot clé qui s'applique à un attribut ou une méthode et qui permet de
déclarer sans prendre compte des instances de la classe.
Exemple :

Imaginons qu'on est dans une classe Produit et qu'on met l'attribut nbProduit déclaré
comme ceci. static int nbProduit;
C'est un compteur qui va s'incrémenter dans le constructeur à chaque fois que l'on va
créer un objet Produit. Vu qu'on l'a déclaré static, le compteur va s'incrémenter pour
tout les objets créer et non pas pour un seul objet.

Les méthodes qui sont déclarée static sont les méthodes qui ne s'appliquent pas à un
objet. On les utilise souvent pour les méthodes non liés aux objets qui font du
traitement comme des calculs (la classe Math par exemple qui comporte ces
méthodes) ou qui affichent quelque chose.

Pour appeler les méthodes static depuis l'extérieur de la classe ou elles sont, on les
appelle en mettant en préfixe le nom de leur classe suivi du nom de la méthode.

Ex : nomClasse.nomMéthode.

On utilise également le mot clé static lors des import pour pouvoir importer que les
méthode statique, ainsi que pour pouvoir créer un raccourcis lors de l'appel (voir mot
clé import)

On utilise souvent le mot clé static pour l'usage de constante comme :


public static final int SIZE = 4;

Si on essaye d'importer une méthode qui est une méthode non statique, on a une
erreur de compilation.
8. For

for est un mot clé qui sers à définir une boucle et est utilisé lorsqu'on connais le
nombre d'itération a faire pour le bloc d'instruction dans la boucle. Il traduit le
concept du « pour » en algorithmique, mais en plus de ceci, le for en java offre
d'autres possibilités.

Grammaire

BasicForStatement

for(ForInit(opt);Expression(opt) ; ForUpdate(opt))
Statement

ForInit

C'est la partie qui sers à initialiser la boucle, il est optionnel. On y déclare une
ou plusieurs variable qu'on va déclarer dans la boucle.
Exemple : int i = 0 ;
(int i = 1, j = 2, k = 3)

Si on ne met rien dans le ForInit mais qu'on utilise des variable dans
l'expression ou le ForUpdate qui n'ont pas été déclarée, erreur de compilation. A
noter que si les variables ont été déclarée avant le ForInit, alors cela compilera et la
boucle se lancera normalement, le ForInit pourra être vide dans ce cas là. Si il n'y a
pas de variable utilisée dans l'expression ou le forUpdate ou l'Expression alors le
ForInit peut être vide, cela compilera mais il y'aura une boucle infinie.

Expression

C'est une expression de type booléene, qui est soit vraie soit fause et qui est
utilisée pour stopper la boucle. Il est optionnel.
Ex : a < 10
a≥b

Quand on l'oublie, il n't a pas de condition pour stopper la boucle, du coup, boucle
infinie.

ForUpdate

Le forUpdate est utilisé pour mettre à jour les indices du ForInit car
l'expression va être restesté par la suite et le résultat peut-être changé en fonction de
l'évolution du compteur. Il est facuitatif. On y trouve les pré/posty incrémentation et
pré/post décrémentation. Il peut également contenir une assignation ou un appel de
méthode.

Si on l'oublie, alors il y'aura une boucle infinie.

Statement

Le statement est obligatoire, c'est l'instruction (ou le bloc d'instruction) qui


sera répété, c'est pour boucler sur cette instruction que le for est utilisé. Si les
instruction ne se trouvent pas dans ce Statement, alors elles ne seront pas bouclées.

A noter que toute variable initialisée dans la boucle est inutilisable en dehors.

Exemple de Statement: {} , {;}, {system.out.println « tranquille ou quoi boloss »}

On peut arrêter une boucle en utilisant un break pour stopper avant la fin, de même
qu'on va réintérer une boucle grâce à continue.

On utilise les for étiqueté pour utiliser le break et sortir de plusieurs boucle grâce a
un label.

Il existe d'autres concept de for comme le foreach et d'autres manière de reproduire


une boucle existent comme le while et le do while.

Ex de for:

for (int i = 1 ; i<10 ; i++ ) {


system.out.println(« i ») ;
}

9. Foreach

Le foreach permet de parcourir toutes les valeurs d'un objet itérable.

Grammaire

EnhancedForStatement

for(Type Identifier : Expression) Statement

Type
Les différents type comme int, byte, short, String, boolean etc. Doit être
du même type que ce qui compose l'élément a parcourir sinon erreur de compilation.
(Donc pour un tableau 2D, vu qu'il est composé de tabbleau d'élément, il faudra qu'il
soit un tableau d'élement, ensuite, on refera un foreach pour parcourir le tableau a
une dimension

Identifier

Le nom de la variable du type précédemment écris

Expression

Une expression itérable, comme un tableau qui a été initialisé


précédemment ou encore une liste.

A noter qu'on ne peut pas avoir accès au compteur dans le foreach, ni aux indice et on
ne peut pas modifier le contenu de l'élément Iterable dans le foreach.

L'ordre dans lequel on va parcourir les éléments est l'ordre de l'élément en partant du
début.

Exemple
String [] s = new String [4] ;

for(String sa : s ) {
system.out.println (« sa ») ;
}

Exemple2
ArrayList<Element> element = new ArrayList
for (Element element : elements) {
system.out.println(element) ;
}
Exemple 3

String s [][] = new String [4][4]

for (String [] sas : s) {


for (String sa : sas) {
system.out.println(« affiche le tableau ») ;
}
}

10. Pré/post incrémentation et pré/post décrémentation


Ce sont des opérateurs unaire qui permettrent de modifier une variable numérique
(double, float, char, int, short, byte). Ils permettent d'incrémenter ou de décrémentater
la variable.

Incrémentation

post Incrémentation

i++ permet d'utiliser la variable avant de l'incrémenter

exemples :

1)
i=5;
j = i++ ; // j = 5 ici car on assigne j = i avant d'incrémenter.

2)

int b = 5
int c = 5
i = c++ + b ++
// ici i = 10 car le premier opérande vaudra 5, l'incrémentation se faisant au
moment du '+' dans le calcul ( à la fin de l'expression c++), donc cela fait 5+5

i=c+b
// maintenant i = 6+6 = 12 car les deux variable ont été incrémentée

pré Incrémentation

La pré-incrémentation consiste à incrémenter la variable avant de l'utiliser.

Exemples :

1)

int i = 5
j = ++i ; // ici j = 6

2)

int i = 12 ;
i = ++i + ++i // ici i vaut 13 + 14 donc 27.
Décrémentation

pré décrémentation

La pré décrémentation consiste à décrémenter la variable avant de l'utiliser

Exemple
int i = 6 ;
int j = --i // i vaut 5

post décrémentation

Consiste à utiliser la variable avant de la décrémenter

Exemple :

int i = 12 ;
int j = i-- ; // j vaut 12

Exemples généraux :

- int i = 5
i = i++ + ++i // i vaut 5 + 7 donc 12

- int i = 2
f(i++, --i) // f(2,2)

int i = 2
f(--i, i++) // f(1,1)

11. Final

Le mot clé final indique qu'un élément ne peut-être modifié dans la suite du
programme et que c'est une constante d'un certain type. Il peut s'appliquer aux
méthodes et attributs d'une classe.

Par convention, les variables notée final sont écrite en majuscules (en séparant les
mots par des underscore).

Exemple :

final TypeVariable nomVariable = Expression ;

final int nombre = 12 ;


Quand on utilise final devant un objet c'est la référence qui pointe vers l'objet qui sera
constante et non pas la valeur de l'objet. L'objet sera donc modifiable, mais la
référence sera toujours vers cet objet (modifié).

Si on mer final devant le nom de la classe, la classe ne pourra pas être utilisée pour
l'héritage.

Exemple :

public final class Board

La méthode sera inchangée dans le cas de l'héritage et la classe fille (qui a héritée) ne
pourra pas modifier cette méthode dite final

Pour l'utilisation, on utilise les constantes car on veu parfois qu'une variable reste
constance ertt qu'elle ne subisse aucune modification. Cela est également utile
lorsqu'on veut changer la valeur de cette constante car on a que la déclaration a
modifier.

Exemple de final :

final int X = 2 ;
X=3; // erreur de compilation (RuntimeException)

12. Expression-instruction

Une instruction est caractérisée par un « ; » à la fin de celle-ci. Une expression à un


type et une valeur. Il existe des hybrides entre les deux dès qu'on rajoute un « ; » à la
fin d'une expression et on nomme cela une expression-instruction.

Grammaire

ExpressionStatement

StatementExpression ;

StatementExpression

Assignment
PreIncrementationExpression
PreDécrementationExpression
PostIncrementationExpression
PostDécrementationExpression
MethodInvocation
ClassInstanceCreationExpression

Assignment

C'est une expression ayant une valeur et un type, la valeur est la valeur de la
variable et le type est le type de la variables

LeftHandSide AssignmentOperator Expression

LeftHandSide

Identifier
ArrayAccess

Il est composé soit de l'identifiant (le nom de la variable) soit d'un


élément d'un tableau

Ex : element[i] ou a

AssignmentOperator

= *= /= %= += -=

Ces opérateur sont utilisé pour assigner, il existe le basique = , mais


également le += qui permet d'incrémenter la variable avec l'expression qui suis.

Ex : int somme = 2 ;
somme += 1 // somme = somme + 1

On ne l'utilise pas seulement pour des entiers, cela marche également avec des
char

Ex : char character = 'a' ;


character +=1 // character= b ici

charcater = character + 1 // ne compilera pas, en effet à cause des conversion, on


// devra faire une promotion vers le int et la réponse, sera
// mise dans un char

Il est également important de rappeller qu'on peut assigner quelque chose a


uune variable et non pas a uine expression.

Ex : i = 2 ; ---> OK

i = i = (i*=2) + 1 ---> OK

(i+1) -= 2 ---> Ne compile pas, (i+1) étant une expression.


Appel de méthode

L'appel de méthode est une expression ayant un type (le type de retour
de la méthode) et une valeur (celle retournée par la méthode).

Instanciation de classe

Créer une instance d'une classe est une expression, elle a un type (celui
de l'objet crée) et une valeur (la référence vers l'objet, l'adresse).

Dès qu'on crée un objet, il va directement sur le tas, si on ne le référence plus (via
son adresse- alors le garbage collector va libérer l'adresse mémoire de l'objet.

Pré/Post inc/Décrémentation

voir le 10.
13. Encapsulation

L'encapsulation est un principe de la programmation orientée objet. Cela permet de


cacher l'implémentation d'une classe objet à laquelle on aura accès seulement via les
méthodes proposée. L'encapsulation permet donc de garentir l'intégrité d'un objet en
empêvhant de le modifier autrement que par la méthode proposée.

Cela permet donc de contrôler ce à quoi les autres classe auront accès. On donne
accès juste à ce qui est nécessaire et pas plus. Par exemple, on ne va pas mettre
d'accesseur pour des attributs non utilisé ailleurs que dans la classe elle même.

On déclare généralement les attributs private auxquels on aura accès grâce aux
accesseur (getter) et mutateur (setter). Les méthodes utilisés sont elles déclarée
comme public. On utilise donc la visibilité pour pouvoir régler l'encapsulation.

Getter : Leur but est de renvoyer la valeur d'un attribut

Setter : Leur but est de modifier les attribut via une valeur reçue en paramètre
exemples :

public int getNombre() {


return nombre ;
}

public void setNombre(int nombre) {


this.nombre = nombre ;
}

14. While

Le while traduit le concept du « tant que » en algorithmique. Contrairement au for il


est utilisé lorsqu'on veut arrêter le traitement à un moment donné mais qu'on ne
connais pas le nombre d'itération à l'avance. On quittera le while quand la condition
ne sera plus respectée.

Grammaire

while (Expression) Statement

L'expression est une expression booléene ou Booléene.

C'est dans le Statement qu'on trouve l'incrémentation qui est optionnelle (si
elle n'y est pas, boucle infinie). Contrairement au for, la déclaration de la variable
qui s'incrémente ne se fait pas dans le while mais avant. L'incrémentation doit
également avoir une influence sur l'expression booléene afin d'éviter les erreurs du
type RunTimeException lorsque, par exemple, on dépasse un tableau.
Exemple :

int [] tab = new int [6]


int n = 6, i=0 ;
boolean trouvé = true ;
while (i< n ET trouvé) {
if(tab[i]==2) {
trouve = faux ;
}
i++ ;
}

// Quand on atteins la fin du tableau ou qu'on trouve 2 dans le tableau, on


s'arrête.
On peut effectuer le même traitement qu'un for avec un while en utilisant cette
grammaire

while(Expression) {
Statement
ForUpdate
}

Dowhile

Contrairement aux idées reçue, il ne représente pas le « faire jusqu’à ce que »


vu en cours d'algorithmique. Il représente plutôt une sorte de « faire tant que ». On
peut traduire le « faire jusqu’à ce que » vu en algo en inversant la condition du do
while (si elle est vrai, la mettre fausse)

Grammaire

do Statement while (Expression) ;

Le do while fait au moins une itération avant de vérifier la


condition.
Le Statement contiens l'instruction à executer au moins une fois.
L'expression est l'expression booléene.
Exemple :

int i = 9 ;
do {
i+=1 ;
} while( i == 10) ;

15 .Throws/throw
Le mot clé throw permet en java de lancer une exception . Une exception surviens
lorsqu'une erreur est détectée, comme par exemple lorsqu'on ouvre un fichier qui
n'existe pas ou lorsque l'utilisateur entre des données incorrecte.

Dès lors on peut se demander pourquoi jeter une exception. Une exception est jetée
lorqu'on vérifie les contraintes liés a une partie du code et lorsque cette contrainte
n'est pas respectée. Par exemple si on demande a l'utilisateur d'entrer un nombre
positif et qu'il entre un nombre négatif on peut choisir de lancer une exception dès la
détection du problème afin que cette erreur ne se propage pas dans le reste du code.

Grammaire : throw Exception;

L'Exception est un objet qui fait parti est objets dis Throwable 'Jetable' en français,
Throwable est une classe sous-classe de la classe Object et qui est chargée de traiter
les erreurs. Vu que ce sont des objet il faut créer l'objet afin de pouvoir le jeter et c'est
pour cela qu'on utilise

throw new TypeException(''message'') ;


ou
throw new TypeException() ;

On créer un nouvel objet Exception auquel on envoie le message qui est la raison afin
de créer cet objet. Il faut savoir qu'on peut créer ses propres exception en utilisant la
notion d'héritage. On crée une classe avec un nom d'exception qu'on fait hériter de la
classe Exception en utilisant le mot clé extends. Le constructeur de cet objet fait
appel au constructeur du parent via « super » en lui envoyant le message qui sera
affiché lors de l'exception, mais on peut aussi ne pas mettre de message, ce n'est pas
obligatoire

Vu qu'une exception est un objet, on peut utiliser le getter getMessage(), cette


méthode viens de la classe Throwable pour obtenir le message qui sera affiché.

Les deux sous-classe de Throwable sont Error et Exception.

La classe Error représente une erreur grave qui provoque l'arrêt de la machine
virtuelle Java, on ne s'en releve pas.

La classe Exception représente d'autres erreur qui sont soit des erreurs personnalisées
comme vu ci-dessus, des erreur du type RuntimeException (qui sont directements liés
a l'incompétance du programmeur comme par exemple NullPointerException ou
ArrayOutOfBandException) ou les deux (des exception créer qui héritent de
RuntimeException).

Si on créer son exception personnalisée (CheckedException), les méthodes qui


peuvent lever ces exception doivent comporter le mot clé throws ou via un try-catch.
Ceci ne vaut pas pour les Error ou RunTimeException qui n'ont pas obligatoirement
besoin de cette clause throws.

Exemple : Identifier returnType MethodName() throws TypeException {

Si on ne le précise pas, le compilateur nous dis que nomException doit être attrapée
ou qu'on doit utiliser le mot clé throws dans l'entête. Ce mot clé indique qu'il est
possible que la méthode lance cette exception. On dis que l'expression est relancée

Pour les expression dites CheckedException, ce sont les exception qui doivent être
contriôlée par le compilateur, il y'a des stratégie de gestion car ces exception doivent
être gérées. On peut jeter l'exception via un throw ou un try-catch ou encore une autre
statégie de gestion (que j'ai pas noté) ainsi que combiner les deux stratégie.

Exemple

public void pasNégatif() throws NegatifException {


n = scanner.nextInt();
if (n<0) {
throw new NegatifException(« Le nombre ne peut etre négatif ») ;
}
}

avec NegatifException déclaré précédement

public class NegatifException extends Exception {

public void NegatifException(String msg) {


super(msg) ;
}
}

16. Enumeration

Une énumération est un ensemble fixe (et petit) de valeurs sémantiquement lié.
Quand on a peu de valeurs, il est conseillé de déclarer une énumération.
L'énumération agis comme une classe car elle peut avoir des attribut et des méthodes
comme une classe, mais elle a également d'autres fonctionnalité comme le fait que les
valeurs de l'énumération sont convertis automatiquement en chaîne. Il peut aussi
apparaître dans un switch ou encore fournir un tableau avec les valeurs de
l'énumération ( via values()). Les énumération héritent de java.lang.Enum
Grammaire

EnumDeclaration

[ClassModifier] enum Identifier [SuperInterfaces] EnumBody

Le ClassModifier est la visibilité donc public, private, protected (package si rien).


l'Identifier est le nom qu'on donne a l'Enumeration par exemple Saisons. Les
SuperInterfaces sont les interfaces si il y'en a (via extends)

EnumBody

{EnumConstants(opt) ,(opt) EnumBodyDeclaration(opt)}

Il contient les valeurs de l'énumération (optionnel) ainsi que le reste de la classe


(optionnel). La virgule est également optionnelle car on peut avoir une seule valeur
dans l'énumération.

EnumConstants

EnumConstant
EnumConstants, EnumConstant

Ce sont les valeurs que peuvent prendre l'énumération, il peut en y avoir aucune ou
autant qu'on veut, cela compile.

EnumConstant

Annotation(opt) Identifier Arguments(opt) ClassBody(opt)

Identifier c'est le nom de la valeur que peut prendre l'énumération. Arguments c'est
les paramètres que peuvent prendre l'énumération (ils doivent être entre parenthèse),
car l'énumération peut contenir un constructeur et des attributs pour chaque valeur,
elle peut aussi en avoir aucun, cela compile. ClassBody c'est le reste de la classe.
EnumBodyDeclarations

; ClassBodyDeclarations(opt)

Une fois que toutes les valeurs que peut prendre l'énumération ont été déclarés, il faut
mettre un ;, sinon erreur de compilation, on pourra continuer d'écrire la classe avec un
ClassBodyDeclarations ou par exemple il y'aura un constructeur et des méthodes
pour l'énumération, on peut aussi ne rien mettre.

Par convention, on met les valeurs de l'énumération en majuscule car ce sont des
valeurs constantes.
Exemples :

public enum Semaine {


LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI,
DIMANCHE ;
}

Il existe des méthodes propre aux classe enum. C'est le cas de values() qui renvoie un
tableau a une dimension avec toutes les valeurs de l'énumération. C'est assez pratique
pour la parcourir avec des foreach.

for(Color color : color.values()) {


system.out.println(« la couleur est » + color ») ;
}

On peut également attribuer un constructeur, des méthodes et des attributs a une


énumération. En rajoutant un constructeur, il faudra mettre entre parenthèse les
paramètres après chaque valeur de l'énumération.

public enum Blocus {


LUNDI(« étude »), MARDI(« glande », MERCREDI(« glande »,
JEUDI « glande », VENDREDI « glande », SAMEDI « glande »,
DIMANCHE « pleure »;
}
avec l'attribut

private String travail;

et le constructeur :

public Blocus(String travail) {


this.travail = travail ;
}

et la méthode

public String getTravail() {


return travail;
}

qu'on appellera via Blocus.LUNDI.getTravail()

17. Copie profonde/superficielle


Une copie superficielle est une copie d'objet dans laquelle la modification de l'objet
original modifiera également l'objet qui contiens la copie tandis que la copie profonde
crée réellement un second objet ayant les même caractéristiques que le premier.

Dans le cas de la copie superficielle, l'avantage c'est que les performances du


programmes sont meilleures, mais une modification d'un objet modifiera le second.
Pour la copie profonde, l'avantage c'est que les deux objets sont indépendant, mais les
performances du programmes sont moins bonnes car cela demande plus de
ressources.

Copie Superficielle

On peut l'effectuer via une simple assignation. Imaginons des objets Personne ayant
un attribut « nom ». Grâce a cette copie, les deux objets pointent vers la même
référence en mémoire, mais si on modifie personne1, alors personne2 sera également
alteré, si on modifie la copie, l'original sera également altéré.

Personne personne1 = new Personne(« hmidou ») ;


Personne personne2 ;
personne2 = personne1 ;
personne1.setNom(« leaderPrice ») ; // personne2.nom vaudra aussi « LeaderPrice »

On peut également faire une copie superficielle avec la méthode clone() de la classe
Object. L'utilisation de cette méthode est déconseillée car elle est mal concue. Cette
méthode peut convenir pour créer faire une copie d'attributs de type primitifs ou
immuables (qui ne changeront pas), si on a des attributs mutables, il faudra procéder
à la réécriture afin de pouvoir eux même les cloner (la classe qui contiens l'overriding
implémente l'interface Cloneable).

Dans le cas des tableaux, lorsqu'on clone un tableau a une dimension, il n'y a pas de
problème, par contre, dans le cas de tableaux a plusieurs dimension, seul le premier
tableau est cloné… C'est l'une des raisons pour laquelle clone() est déconseillé, il
faudra donc procéder a un overriding avant de l'utiliser pour pouvoir cloner le
tableau.

Exemple de clone sans overriding:

Personne personne2 = personne.clone();

Pour les copies de tableau, on peut également utiliser une méthode de la classe Arrays
qui se nomme copyOf() qui permet de copier tout le tableau ou une partie (et qui
completera la partie manquante du tableau par des null. A noter que si l'on modifie le
tableau original par la suite, le tableau copié sera également modifié.

Exemple copyOf :
String [] afou = Arrays.copyOf(fayen, fayen.length);

Copie profonde

Pour les objets on utilise une technique qui se nomme « constructeur par copie » afin
de recréer un objet ayant une autre référence mais les même caractéristiques que
l'original. On le fait en créant un second constructeur dans la classe de l'objet qu'on
veut copier. Ce nouveau constructeur reçois l'objet à copier en paramètre et crée un
nouvel objet avec les même caractéristiques.

Exemple :

public Personne Personne(personne) {


this(personne.nom) ;
}
personne2 = new Personne(personne)

Ainsi les références ne seront plus les mêmes et si on altère l'original, la copie reste
intact.

On peut l'effectuer pour les tableau et les tableaux a plusieurs dimensions via la
méthode copyOf() à laquelle on rajoutera ce concept de constructeur par copie. En
effet, on crée un nouvel objet ayant seulement la longueur du premier tableau, ensuite
on fait une boucle qui utilisera copyOf() pour copier chaque tableau de tableau et
ainsi éviter tout problèmes.

Exemples :

afou = new MyObject [fayen.length][] ;


for(int i = 0 ; i < = fayen.length ; i++) {
afou[i] = Arrays.copyOf(fayen[i],fayen[i].length) ;
}

Pour les tableaux, on peut également faire des copie profondes avec deux boucles for,
c'est fastidieux mais c'est une copie profonde et on ne rencontrera pas de problèmes.

afou = new MyObject[fayen.length][] ;


for(int i = 0 ; i< fayen.length ; i++) {
afou[i] = new MyObject[fayen[i].length] ;
for (int j = 0 ; j < fayen[j].length ; j++) {
afou[i][j] = fayen[i][j] ;
}
}
On crée un tableau en connaissant la taille du premier tableau de l'original. Ensuite
pour chaque tableau de tableau on en crée un nouveau dans la copie.

Pour les tableaux, on peut également mélanger les deux méthodes, celle des boucles
et du constructeur par copie. Cette technique sera très serviable pour les tableaux
d'objets, afin de faire une copie profonde et sans risque, on nomme cela la copie
profonde défensive.

Exemple :

afou = new MyObject[fayen.length][] ;


for(int i = 0 ; i< fayen.length ; i++) {
afou[i] = new MyObject[fayen[i].length] ;
for (int j = 0 ; j < fayen[j].length ; j++) {
afou[i][j] = new Personne(fayen[i][j]) ;
}
}

18. Try Catch

Les mots clé try et catch sont utilisés pour traiter et gérer les exceptions qui peuvent
survenir dans un programme. Globalement, l'instruction try-catch se présente comme
ceci. On met les instructions qui peuvent mal se passer dans le bloc try{}et si une
exception surviens, il y'a dans le catch {} les instructions va régler le problème. Ces
deux mots clés sont indissociables les uns des autres, il ne peut y avoir de try sans
catch et inversément.

Exemple :

int a = 100 ;
try {
int b = scanner.nextInt() ;
int c = a/b // si on a rentré 0, il y'aura une exception car on ne peut pas
diviser par zéro
} catch(Exception e) {
system.out.println(« Division par 0 impossible ») ;
}
Quand une instruction se passe mal dans le try, le code du try est interrompu, et le
code du catch est exécute. Une fois que le code du catch est terminé, on exécute la
suite du programme qui était après le bloc try-catch.

On remarque que pour le catch, il faut définir le type et le nom de l'exception qui
pourra être attrapée. En ne précisant pas et en mettant Exception, on est certain que
tout type d'Expression sera catché car toutes les exceptions héritent de la classe
Exception. Mais on peut également choisir de n'attraper que les
IllegalArgumentException, les QuartoException(si elle a été crée) ou d'autres types
d'exception, pour ce faire il suffit simplement de modifier les parenthèse qui suivent
le catch.

Exemple

try {

} catch (IllegalArgumentException argu) {

}

Etant donné que l'Exception est un objet, elle a des méthodes. Pour pouvoir utiliser
les méthodes de l'Exception comme par exemple getMessage(), on utilise :

Identifier.MethodName() ;

Un try peut avoir plusieurs catch afin de catcher plusieurs exception et reserver un
traitement spécial à chacune des exception. L'ordre ici est très important car il faut
commencer par le plus pertinent jusqu'au moins pertinant.

Ex :

try {

} catch(IllegalArgumentException e) {

} catch(QuartoException ex) {

}

Quand le traitement à faire est le même pour plusieurs types d'expression qu'on veut
catcher, on peut utiliser les catch multiples avec l'opérateur | pour déterminer séparer
les type d'Exception.

Ex :
try {

} catch(QuartoException | IllegalArgumentException e) {

}

On remarque qu'il n'y a qu'un seul Identifier qui est déclaré a la fin de la parenthèse.
En fonction de l'exception qui est catchée en premier, les méthodes renverront un
résultat différent.

Par exemple, si mon IllegalArgumentException affichait comme message « Pas de


division par zéro » et ma QuartoException affichait « pas de piece sélectionnée » et
que c'est la QuartoException qui est catchée alors lorsqu'on fera e.getMessage, c'est
le message de la QuartoException qui sera sélectionner.

Finally

Le mot clé finally consiste à exécuter une partie de code quoi qu'il arrive, même si
l'exception surviens dans le try et que le try est interrompu ou même en cas
d'instruction break ou continue, la partie du code dans la clause finally sera exécutée.
finally n'est pas indépendant, il doit être accompagné d'un try et donc d'un catch, il
peut se placer avant ou après le catch. Ce mot clé est utilisé pour libérer les
ressources. Les ressources sont des objets qu'on peut ouvrir et qu'on doit fermer
lorsqu'ils ne sont plus utilisés, comme par exemple des flux. Avant ce moyen était le
seul pour pouvoir s'assurer que ces ressouces allaient se fermer normalement.
Maintenant il existe une alternative pour pouvoir fermer ces ressources quoi qu'il
arrive. On l'appelle try-with-ressources.

Exemple de finally :

try {

} catch(Exception e) {
….
} finally {
flux.close()
}

Try with ressources

Les try with ressources permettent de déclarer une ou plusieurs ressources, une
ressource est un objet ayant besoin d'être fermé lorsqu'il n'est plus utilisé. Grâce au
try with ressources, on est assuré que chaque ressource sera fermée lorsqu'elle ne sera
plus utilisée. Il n'est plus nécessaire de fermer les ressources grâce a la méthode
close() et il ne faut pas le faire.

Les ressources qui seront fermées se trouveront dans une parenthèse qui suis le try.
On peut toujours utiliser des clause finally mais la fermeture des ressources se fera
avant l'execution de ces clauses. A noter qu'il est obligatoire de définir les ressources
a fermer dans les parenthèses qui suivent le try, sinon, erreur de compilation.

Exemple :

try(BufferedReader bufferedReader = new BufferedReader(new

03.FileReader("C:/Users/jm/AppData/Local/Temp/monfichier.txt")
)) {

String ligne = bufferedReader.readLine() ;

} catch (IOException io) {



}

A la fin du bloc la ressource bufferedReader sera donc fermée sans qu'on ait besoin
d'utiliser la méthode close(). La ressource sera fermée a la fin des instruction, qu'elles
se soient bien passé (fin du try, pas besoin d'aller dans le catch) ou mal
passée(passage par le catch).

19. Héritage

L'héritage est un principe de la programmation orienté objet. Ce principe nous permet


d'utiliser une nouvelle classe (dite classe fille) à la base d'une autre classe (dite classe
mère). La classe fille va hériter des attributs et des méthodes de la classe mère et
pourra y ajouter des fonctionnalité et même réécrire les méthodes (overriding).

Pour cela on utilise le mot clé extends qui va suivre le nom de la classe mère dans
l'entête comme ceci :

public class nomClasseFille extends nomClasseMere {



}

Les attributs et les méthodes de la classe mère doivent être visible dans la classe fille.
Pour cela aux lieux de mettre les champs private on les met protected, ainsi ils seront
visible dans la classe fille.

L'overriding est le fait de réécrire une méthode afin qu'elle puisse nous rendre service
pour la classe fille car celle de la classe mère est obselète pour la classe en question.
Imaginons le cas de la méthode toString() de la classe mère qui avait été définie. Si
on rajoute un attribut et qu'on voudrait l'inclure dans le toString(), il faudra réécrire la
méthode et rajouter ce qu'on veut à la méthode, ainsi la méthode de la classe mère est
ignorée au profit de la méthode qui a été réécrite.

Toutes les classes dans le langage java héritent d'une classe qui est la classe Object, la
seule classe qui n'hérite d'aucune autre classe c'est Object. La déclaration est
implicite, nous n'avons pas besoin de faire a chaque fois extends Object mais si nous
le faisons ça ne change rien.

Ex :
public class Board ---> public class Board extends Object

Donc toute les classe en java héritent de Object et des méthodes qui lui sont propre.

Une classe qui est dites final ne pourra pas avoir de classe fille et faire hériter, même
si elle même peut être la classe fille d'une classe non final. Une méthode final est une
méthode qui ne pourra être réecrite dans la classe fille.

L'héritage inclus également un autre mot clé super qui fait référence à la classe
parent. Ainsi on pourra l'utiliser dans le constructeur de la classe fille pour créer un
objet via super(param) ou faire appel aux méthodes ou aux attributs de la classe mère
via super.nomMéthode() ou super.nomAttribut.

En Java, on ne peut hériter que d'une seule classe a la fois(hormis l'héritage implicite
de Object). Mais la solution pour remédier a ce problème c'est d'implémenter
plusieurs interfaces via le mot clé implements. En effet, une interface peut hériter
d'autant d'interface qu'elle veut via extends et on peut implémenter autant d'interface
qu'on veut. A l'inverse, une classe peut avoir une infinité de classe fille.

Exemple :

public class PointNomméColoré extends PointColoré implements Point


implements ...

Les méthodes statique (qui appartiennent à la classe) ne peuvent être overrides, il ne


peut y avoir qu'un exemplaire de méthode statique.

On ne pourra pas instancier un objet de la classe fille avec la classe mère, par contre,
on peut instancier un objet de la classe mère avec la classe fille, mais les attribut et
les méthodes de la classe fille ne seront pas accessible pour cet objet de la classe
mère. Pour instancier un objet de la classe fille avec la classe mère on peut tenter de
faire un cast, il n'y aura pas d'erreur de compilation, mais il peut y avoir une
exception a l'exécution.
Exemple avec Chomeur qui hérite de Esi

Esi esi = new Chomeur() // ça compile et ça marche


Chomeur etudiant = new Esi() // ne compile pas
Chomeur etudiant = (Chomeur) new Esi() //compile mais p-ê erreur d'execution cast
impossible

L'héritage est également utilisé avec un autre concept, celui des classes abstraites.
Une classe abstraite est une classe qui ne peut pas produire d'instances, a l'inverse des
classe concrète vues jusqu'à là. Ceci implique donc que ces classes abstraites ne sont
utilisés que par leur classe fille.Pour les déclarer, une utilise le mot clé abstract. Le
rôle de ces classe est la factorisations des fonctionnalités commune a plusieurs classe.

Par exemple, si je sais que dans une classe Triangle et une classe Rectangle je vais
devoir utiliser une méthode qui déplace les coordonnées et que le mécanisme est le
même pour les deux classe, je peux créer une classe abstraite dont vont hériter les
deux classes Rectangle et Triangle afin de pouvoir avoir moins de code a écrire, cela
simplifie donc l'écriture.

Exemple d'héritage

public class Point {


protected double x ;
protected double y ;

public Point(double x, double y) {


this.x = x ;
this.y = y ;
}
protected display() {
system.out.println(« le point est en » + x + « , » + y ») ;
}
}

public class PointNommé extends Point {

private String nom ;


public PointNommé(double x, double y, String nom) {
super(x,y) ;
this.nom = nom ;
}
@Overriding
private display() {
system.out.println(« le point est en » + x + « , » + y + « et s'appelle » + nom) ;
}
}

20. Instanciation

Une instance d'une classe est un objet avec un état, déterminé par la valeur de ses
attributs, et un comportement qui dépends de la valeurs de ses attributs vis a vis d'une
méthode. Une instance d'une classe est un exemplaire de la classe ayant les mêmes
caractéristiques. On appelle plus communément l'instance d'une classe, un objet. Une
classe peut avoir autant d'instance qu'on veut.

L'instanciation d'une classe est précédé par la déclaration de l'objet. La déclaration de


l'objet consiste a créer une référence sur la pile, cette déclaration est ensuite suivie de
l'instanciation qui se déroule en deux étapes, dans un premier temps l'utilisation de
l'opérateur new qui va réserver l'espace mémoire nécessaire pour contenir toutes les
informations de la classe et ensuite l'appel du constructeur pour créer l'objet sur le tas.
Exemple de déclaraion :

TypeObjet nomObjet ;

TypeObjet est le nom de la classe, le modèle de l'objet qu'on va créer, l'objet est le
nom qu'aura réelement l'objet lorsqu'on fera appel a lui pour l'utiliser. On remarque
que la déclaration ne se fait pas comme avec les type primitifs prédéfinis mais avec
un type référence, car les objets sont, comme les tableaux, des type référence.

L'instanciation est donc séparée en deux étapes, l'utilisation du new qui va réserver
l'espace mémoire pour contenir l'objet et l'initialisation de l'objet via le constructeur
en lui fournissant (ou non, dépends du constructeur) des paramètres afin qu'il puisse
fixer l'état de l'objet avec les paramètres qu'on lui donne (ou non). Ainsi, on aura
créer un nouvel objet sur le tas.

Exemple d'instanciation :

new TypeObjet( param(opt), …) ;

A noter qu'on peut procéder à la déclaration et l'instanciation en une seule instruction


en procédant comme ceci :

TypeObjet nomObjet = new TypeObjet ( param (opt), …) ;

Une fois que ceci est fait, l'objet existe réelement sur le tas et on pourra alors l'utiliser
et utiliser ses méthodes ou ses attributs afin de procéder au traitement voulu.Les
instances d'une classe sont indépendantes l'une de l'autre sauf si il y'a un membre
statique, dans ce cas là, toutes les instances de la classe partagent le même membre.
21.Instanceof

Grammaire : un Objet instance uneClasse

But : Tester si un objet passé en paramètre est une instance d’une classe déterminée et
retourne une valeur booléenne, true si unObjet est une instance de la classe
uneClasse, false sinon.

Exemple :
public class Point {
private int x,y;
public Point(int abs, int ord){
x = abs;
y = ord;
}
public static void main(String[] args) {
Point p = new Point(2,3);
System.out.println(p instanceof Point);
}
}
Affiche true car p appartient à la classe Point.

Autre exemple :
public class Point {
private int x, y;
public Point(int abs, int ord) {
x = abs;
y = ord;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Point)) { //On aurait pu mettre if( o.getClass() !
=this.getClass())
return false;
}
Point point = (Point) o;
return this.x == point.x && this.y == point.y;
}
public static void main(String[] args) {
Point p = new Point(2, 3);
Point p2 = new Point(2, 3);
System.out.println(p.equals(p2));
}
}
La première chose faite est de tester si l'objet passé en paramètre est bien de la
classe Point et s’il est non nul (dans le cas contraire on retournera false). Instanceof
permettra de tester la classe d'un objet. En l'occurrence, il retourne true pour tous les
objets de la classe Point, et de toute classe qui hériterait de Point. Une fois que nous
sommes sûr d'avoir un objet Point en paramètre, alors il nous faut comparer ses
champs un par un. Pour pouvoir accéder à ses champs, il faut le convertir en objet
de la bonne classe et c’est là qu’intervient le casting ! Elle consiste à déclarer un
objet (ici point), et à lui affecter la valeur de l'objet à convertir, en mettant devant et
entre parenthèses le type dans lequel on veut faire cette conversion.

22. Le Temps :

Représenté sous la forme ISO8601.


yyyy-mm-ddThh :mm :ss [TZ]

Temps Machine :
2 classes : java.time.Instant => représente un temps machine (timestamp).

Nbres sec écoulées depuis 1janvier 1970 && Valeur stocké dans un long.

Exemple :

Instant instant = Instant.now() ;


System.out.println(instant) ; //affiche la date d’aujourd’hui en format iso8601
Instant parse = Instant.parse("1946-02-01T01:30:00Z"); // Crée une date à partir
//d’une chaine sous le bon format.
Java.time.Duration => représente une période de temps (machine).

Exemple :
Instant instant = Instant.now() ;
Instant DeuxMinutesPlusTard = now.plus(Duration.ofMinutes(2)) ; // affiche l’heure
//actuelle avec deux minutes supplémentaires.
Voir la période entre deux moments :
Instant now = Instant.now();
Instant now1 = now.plus(Duration.ofHours(5).plusMinutes(4));
Duration dur = Duration.between(now, now1);
System.out.println(dur) ; // représente une période sous la forme iso8601.
Temps humain :

Classe : java.time.LocalDateTime et java.time.LocalDate => représente une date


avec ou sans heures.

Exemples :

LocalDateTime birth = LocalDateTime.of(1995, Month.DECEMBER, 9, 10, 30);


System.out.println(birth);
System.out.println(birth.getDayOfWeek());
DateTimeFormatter form = DateTimeFormatter.ofPattern("EEEE dd MMMM
YYYY k:hh");
System.out.println(birth.format(form));

//On affiche premièrement une date (ici l’année de naissance où Month est une
//enum)
//On affiche ensuite seulement le jour de la semaine de cette naissance.
//Et ensuite on fait un affichage sous le format DateTimeFormatter (en français
//ici).
//Pour mettre sous un format anglais on rajoute alors :
System.out.println(birth.format(form.withLocale(Locale.ENGLISH)));

Différence entre Duration et Périod :

Duration, qui représente une durée en millisecondes, souvent récupérée à partir d’un
intervalle.
Period ne représente pas une durée de longueur fixe et bien définie entre deux points
dans le temps, mais une durée conceptuelle "flottante", de durée réelle variable (ex:
un jour, un mois, un an...). Cela permet d'effectuer des calculs assez naturels comme
"ajouter un mois", indépendamment du nombre de jours réel par mois.

Java.time.Period => représente une période de temps.


LocalDate date = LocalDate.of(2005,11,21) ;
Period since = date.until(LocalDate.now()) ;
System.out.println(since.toTotalMonths()) ;
// Affiche le nombre de mois entre les deux dates.
ChronoUnit (enum sur les unités de temps)

Ex : LocalDateTime birth = LocalDateTime.of(1995, Month.DECEMBER, 9, 10,


30);
System.out.println(birth.until(LocalDateTime.now(),ChronoUnit.DAYS) ;
// Affiche le nombre de jour entre la date d’aujourd’hui et celle de birth.
Il n’y a pas que le calendrier ISO, il se base sur le calendrier Grégorien.
Exemple : LocalDate date = LocalDate.of(2005,11,21) ;
System.out.println(JapaneseChronology.INSTANCE.date(date)) ;
(Voir les différents calendriers) =>
System.out.println(Chronology.getAvailableChronologies()) ;

23.Méthode :

C’est une boîte noire définie par un nom et un ou plusieurs paramètres, qui en fin
d’exécution fournit un résultat qui varie selon la valeur du ou des paramètres.
Java propose des méthodes prédéfinies, mathématiques ou non, très utiles.

Pour appeler une méthode qui se trouve dans une autre classe :
NomClasse.nomMethode();

Si elle se trouve au sein de la même classe

il suffit de juste mettre le nom de la méthode suivi de ses paramètres (s’il en


possède).

Le type et l’ordre des paramètres doivent être respectés, sous peine d’une erreur de
compilation. Dans le cas où la méthode possède plusieurs paramètres, ceux-ci sont
séparés par des virgules et devant chaque paramètre, est placé son type, même si deux
paramètres consécutifs possèdent le même type.
Le nom de la méthode est choisi en fonction à pouvoir représenter ce qui sera réalisé
par son intermédiaire, et est écrit en minuscule sauf pour les initiales de chaque
nouveau mot.

Toute méthode fournissant un résultat possède une instruction return suivie du


résultat, placée dans le corps de la méthode (dans ce cas-ci, à l’entête de la méthode
on mettra également son type de retour)

Exemple : public typeResultat nomMéthode (paramètre(s)){}


Une méthode qui ne retourne pas de résultat possèdera dans son entête, à la place de
son type de retour, un type void.
Exemple : public void nomMethode(paramètre(s)){}
La méthode main() est considéré par l’ordinateur comme la méthode principale qui
sera exécutée une seule fois, par l’interpréteur java lors du lancement du programme.
Une méthode main() ne peut être appelée par une autre méthode du programme. Et
elle est toujours static. Exemple : public static void main(String[]args){}

Remarque : On peut avoir plusieurs méthodes du même nom mais alors avec des
arguments différents !

24.Constructeur

C’est une méthode sans valeur de retour qui est utilisé pour initialiser les données
d’un objet au moment de sa déclaration en mémoire et de le créer.

Exemple : NomClasse nomVariable = new NomClasse () ;

Les constructeurs portent le même nom que la classe où ils sont définis et peuvent
avoir un nombre quelconque de paramètres. S’il n’y a aucun constructeur, java
propose un constructeur par défaut qui est initialisé à 0 ou à null en fonction de ses
données ( Possibilité d’avoir plusieurs constructeurs dans une même classe à
condition que les paramètres soient différents).

Exemple d’un constructeur :

public class Point {

private double x,y ;

public Point (double x, double y) { //constructeur à // 2 paramètres.


this.x = x ;
this.y = y ;
}
}

Il est possible de faire appel à un constructeur se trouvant dans la même classe par le
mot clé this.
Exemple :

public class Etudiant {


private String nom ;
private int annee ;
private boolean reussi ;
public Etudiant (String nom, int annee, boolean reussi){
this.nom = nom ;
this.annee = annee ;
this.reussi = reussi ;
}
public Etudiant (String nom, int annee){
this(nom, annee, true) ;
}
}

Il est également possible de faire des tests de validité sur les paramètres entrés
dans le constructeur pour s’assurer que l’objet se créée dans un été valide.
Utilisation d’un if par exemple pour voir si un nombre n’est pas inférieur à 0.

25.Package

Groupement de classes Java. Le package détermine où le byte code est cherché (le
.class). L’attribution d’un nom de package se fait au niveau du fichier source, en tout
début de fichier, comme ceci :

package nomPackage ;

Pour utiliser une classe appartenant à un package il est important de fournir son nom
qualifié (cité son nom de package avec son nom de classe), comme ceci :

nomPackage.nomClasse

Il est également possible d’accéder aux classes d’un package faisant partie d’un
package différent par un import de ce package :

import nomPackage.* ; A écrire dans le fichier source.

Pour que le compilateur puisse trouver un package, Java utilise une variable
d’environnement appelée CLASSPATH donnant la liste des chemins d’accès aux
classes.
Exemple :
On crée une classe Test dont le package est package g39753.quarto.view;

Le fichier Test.class doit alors se trouver dans le répertoire /« valeur du


CLASSPATH »/g39753/quarto/view

Si une classe ne possède pas de package, le compilateur considère que les classes
appartiennent au package par défaut (pas besoin de spécifier le chemin d’accès).
Il existe aussi un paquetage particulier appelé java.lang qui est importé
automatiquement par le compilateur. Ce qui permet d’utiliser les classes standards
telles que Math,System,.. Sans devoir importer un package dans le fichier source.

26.This/Super :

This : sert à référencer l’instance de l’objet en cours d’utilisation (référence à soi-


même). Il permet une meilleure lisibilité du code et de différencier l’objet courant
d’une variable reçu en paramètre portant le même nom.

Exemple :

public class Point{

private int x,y ;

public Point(int x, int y){


this.x = x ; // Au lieu de x = x ;
this.y = y ; // Au lieu de y = y ;
}
}

On peut également utiliser this comme un nom de méthode au sein d’un constructeur
pour appeler un autre constructeur de la même classe.

Exemple :

public class Point{

private int x,y ;

public Point(int x, int y){


this.x = x ; // Au lieu de x = x ;
this.y = y ; // Au lieu de y = y ;
}
public Point(){
this(1,1) ; // Va faire appel au constructeur Point avec deux entiers en
//paramètres
System.out.println(Coucou) ;
}
public static void main(String[]args){
Point a = new Point(0,0) ; // Affichera 0 0
Point b = new Point() ; // Affichera 1 1 et ensuite le message Coucou
}
}

On peut également faire appel à une méthode de la classe dans le constructeur avec le
mot clé this.

Exemple :

public MaClasse(String att){


this.att = at ;
this.refreshAtt() ; // Appel d’une méthode de la classe.
}

Super :

Il fait référence au constructeur parent et doit être la première instruction dans un


constructeur enfant. On parle ici d’héritage car pour référencer d’un constructeur
parent on doit hériter de celui-ci, et on peut le faire grâce au mot clé extends où on va
récupérer les attributs et les méthodes du parent.

Exemple :

public class Point {


public Point (double x, double y) {…}
}

public class ColoredPoint extends Point {


private Color color ;
public ColoredPoint (double x, double y) {
super(x,y) ; // on fait appel au constructeur de la classe Point
color = Color.BLACK ;
}
}
Remarque : Seule les classes en visibilité protected ou public peuvent être utilisée
dans une classe héritée.

On peut également appeler une méthode de la classe parent par exemple :

public class A {
public getA(){..}
}

public class B extends A {

public salam (){


super.getA () ; // va utiliser le getA() qui se trouve dans la classe A.
}
}

Remarque : Lorsqu’une classe hérite d’une autre, dans le constructeur enfant, super
est appelé implicitement (s’il n’est pas présent) pour faire appel au constructeur
parent sans paramètre, sauf s’il existe un constructeur avec paramètre dans le parent.

Faire appel à un attribut du parent :

public class A {
public int nb ;
public A (int nb) {
this.nb = nb ;
}
}

public class B extends A {


public B (int nb) {
super (nb) ; // Fait appel au constructeur de la classe mère.
}
}
public String toString () {
return super.nb ; // Appel de l’attribut de A (attention à la visibilité !
}
}
27. Implements

Implements permet à une classe d’implementer une interface. Une interface


correspond à une classe qui définit non pas un modèle d’objet, mais un ensemble de
comportements possibles, sans que ces comportements ne soient réellement décrits.
Elle représente un "contrat", ce qu'on attend d'un objet. Une classe est autorisée à
hériter (on dira implémenter) un nombre indéterminé d’interfaces.
Une interface, dans le langage Java, définit les noms des méthodes associées aux
comportements.

public interface uneInterface {


public type methode1() ;
public type methode2() ;
// d’autres en-têtes de méthodes
}

Une interface est définie au sein d’un fichier qui porte son nom suivi de l’extension
.java. Le terme interface remplace le terme class. Les comportements proposés par
l’interface sont définis à partir des en-têtes de méthodes uniquement (signature).

 - Toutes les méthodes d'une interface sont implicitement abstraites (cf. abstract) on
n’a pas besoin de mettre abstract devant le nom de la méthode.

- Une interface n'a pas de constructeurs

 - Une interface ne peut avoir de champs sauf si ceux-ci sont statiques.

 - Une interface peut être étendue par une ou plusieurs autre(s) interface(s).

 - Une interface peut hériter d’une autre interface (avec extend pas implements !!).

 - En fait, une interface est une classe abstraite dont toutes les méthodes sont
abstraites et dont tous les attributs sont des constantes (cf. final).

Une fois l’interface définie, les méthodes sont concrètement décrites au sein des
différentes classes qui implémentent l’interface.

2) Exemples

public interface Vehicule { // création de l’interface


void rouler();
void freiner();
}
Ensuite si on crée une classe Velo je mets implements Vehicule après le nom de la
classe, et dans les méthodes de la classe Velo on doit écrire les méthodes rouler et
freiner qui sont dans l’interface Vehicule et ensuite on peut les redéfinir (cad coder la
manière dont un vélo roule). On peut le faire ailleurs avec une classe Auto qui a aussi
le implements on peut donc donner plusieurs implémentations de cette interface. Les
2 instances qui vont se faire via ces 2 classes peuvent être vues comme des véhicules,
c'est ce qu'on appelle le polymorphisme.
Si jamais je crée une classe Personne qui possède une méthode conduire qui a comme
paramètre un Véhicule

Personne p = new Personne();


p.conduire (new Velo()); //comme la méthode attend un Véhicule en argument, on
//peut passer tout //objet implémentant cette interface.
p.conduire (new Auto()); //idem

On peut "instancier" un Vehicule avec ses implémentations :

Vehicule v = new Auto();


Vehicule t = new Velo();

Dans ce cas v et t sont vus comme des Vehicule et donc on ne peut appeler sur ces
objets que les méthodes définies dans l'interface Vehicule !!

Exemple 2 :

Interface Comparable

public class Personne implements Comparable<Personne>() {

private int taille ;

public int compareTo(Personne p) {


return this.taille - p.taille ;
}
}
public interface Comparable<E> {
public int compareTo(E o) {
}
}
La méthode compareTo doit comparer l’objet courant (this) à l’objet o reçu en
paramètre et renvoyer un entier (dont la valeur exacte est sans importance) :
- négatif si l’on considère que l’objet courant est «inférieur» à l’objet o (au sens de
l’ordre qu’on veut définir) ;
- nul si l’on considère que l’objet courant est égal à l’objet o ;
- positif si l’on considère que l’objet courant est «supérieur» à l’objet à.
28. Tableau à 1 dimension

Un tableau est une structure de données contenant un groupe d'éléments tous du


même type. Le type des éléments peut être un type primitif ou une classe. Lors de la
définition d’un tableau les [] spécifiant qu’il s’agit d’un tableau peuvent être placés
avant ou après le nom du tableau. Comme toute variable utilisée dans un programme,
un tableau doit être déclaré afin de :

- donner un nom à l’ensemble des valeurs à regrouper ;


- définir la taille du tableau de façon à préciser le nombre de valeurs à regrouper ;
- déterminer le type de valeur à mémoriser.

TypeTableau [] nomTableau ;
nomTableau = new TypeTableau [tailleTableau] ;

• Les crochets [] entre le type et le nom de la variable indiquent au compilateur que la


variable nomTableau représente un tableau. A cette étape, le compilateur réserve un
espace mémoire portant le nom du tableau. Cet espace est susceptible de contenir
l’adresse de la première case du tableau.

• TypeTableau peut être aussi bien un type simple (int, double,...) qu’un type
référence. Dans ce cas, le tableau est un tableau d’objets stockant dans chacune de ses
cases l’adresse d’un objet à mémoriser.

• L’opérateur new réserve autant de cases mémoires consécutives qu’il est indiqué
entre les [], soit tailleTableau. L’opérateur new détermine enfin l’adresse de la
première case du tableau et la stocke grâce au signe d’affectation, dans la case
nomTableau créée à l’étape précédente.

a. Le nombre de cases réservées correspond au nombre maximal de valeurs à traiter.


Lorsque la taille du tableau est fixée après l’exécution de l’opérateur new, il n’est
plus possible de la modifier en cours d’exécution du programme. Cependant, il est
possible de ne pas fixer définitivement la taille du tableau avant compilation en
plaçant une variable entre les [] au lieu d’une valeur numérique.

b. Les tableaux sont des objets. Les objets sont caractérisés par leurs données et les
méthodes qui leur sont applicables. Exemple : .length

c. Lors de la déclaration d’un tableau, il est possible de l’initialiser directement de la


façon suivante :

TypeTableau [] nomTableau = {a, b, c, ...}


Les cases mémoires sont réservées et initialisées dans l’ordre, à l’aide des valeurs
placées entre les { } et séparées par des virgules.
d. Les opérations arithmétiques directes de deux tableaux sont des opérations
impossibles. En effet, chaque opération doit être réalisée élément par élément.

2) Exemples

// ti est un tableau à une dimension de int


int ti [];
// tc est un tableau à une dimension de char
char[] tc;

Un tableau peut être initialisé :

int ti1 [] = { 1, 2, 3 , 4};


char[] tc = {’a’, ’b’, ’c’};

Pour allouer l’espace nécessaire au tableau il faut utiliser new :

// ti est un tableau à une dimension de 10 int


ti = new int [10];
L'utilisation d'un tableau pour lequel l'espace n'a pas été alloué provoque la levée
d'une exception NullPointerException.

Les éléments d’un tableau sont indicés à partir de 0. Chaque élément peut être accédé
individuellement en donnant le nom du tableau suivi de l’indice entre [ ]

ti [0] ;// premier élément du tableau ti


ti [9] ;// dernier élément du tableau ti

L’accès à un élément du tableau en dehors des bornes provoque la levée d’une


exception ArrayIndexOutOfBoundsException

Un tableau possède un attribut length qui permet de connaître le nombre d’éléments


d’un tableau.

ti.length vaut 10.


tc.length vaut 15.

29. Tableau à 2 dimensions

Lors d’une définition de tableau le nombre de crochets indique le nombre de


dimensions du tableau. Un tableau à deux dimensions s’organise non plus sur une
seule ligne, mais sur des lignes et des colonnes. Cette organisation correspond en
réalité à un tableau à 1 dimension, dont chacune des cases contiendrait un tableau à 1
dimension.

Le croisement d’une ligne et d’une colonne détermine un élément donné du tableau.


TypeTab [][] nomTab = new TypeTab[nbLignes][nbColonnes] ;

Le nombre de lignes est donné par l’expression nomTableau.length alors que le


nombre de colonnes est déterminé par l’expression nomTableau[0].length.

Pour initialiser, modifier ou consulter la valeur d’un élément d’un tableau à 2


dimensions, il convient d’utiliser deux indices : un indice pour les lignes et un indice
pour les colonnes.

Chaque indice étant contrôlé par une boucle for, la technique consiste à imbriquer les
deux boucles.
2) Exemples :

int t2[][] = new int[5][10] ;


Définit un tableau à 2 dimensions 5 lignes sur 10 colonnes (ou l’inverse).
t2[i] désigne le ième tableau à une dimension d'entiers.
Un tableau à plusieurs dimensions peut être initialisé :
int t21[][] = {{1, 2, 3}, {4, 5, 6}};
Définit un tableau dont la première dimension va de l'indice 0 à l'indice 1 et la
deuxième dimension de l'indice 0 à l'indice 2.

Toutes les lignes d’un tableau à 2 dimensions


n’ont pas forcément le même nombre
d’éléments :

Exemples qui fonctionnent ou pas pour la déclaration du tableau !!

int [][] test = new int [2]; // Ne fonctionne pas car tu déclares un tabeau multi-
dimension et tu ne donne la taille que d'une dimension.
int [][] entierss = new int [] {1,2}; // Ne correspond pas à la grammaire java, il faut
faire : int[][] entiers = {{1}{2}};
int [][] entiserss = new int [] {{1},{2}};// Aurait pu fonctionner si on avait déjà
déclaré un tableau avant int [][] entiserss = {{5,8,6,0,7},{3,3,2}};,
//et si on avait mis deux paires de crochets vu que c'est deux dimensions.
int [][] salut = new int [2][3]{3,2};// Ne fonctionne car on ne donne pas la taille et les
valeurs en même temps. c'est l'un ou l'autre.

int [][] salut = new int [2][3]{null,null};// Ne fonctionne car on ne donne pas la taille
et les valeurs en même temps. c'est l'un ou l'autre.
30. I/O(Codage, fichier)

1.Codage

Le codage consiste ici a représenter une ou des informations de manière textuelle ou


binaire et la manière de coder dans ces deux cas comporte des différences. En effet le
codage en binaire est la représentation comme en mémoire, et le codage en texte
utilisera une suite de caractère.

Prenons un exemple ou nous codons dans un fichier de manière binaire et de manière


textuelle,nous voulons écrire 32 dans un fichier, en binaire cela donnera :

0000000 0020 0000001 en sachant que la valeur 20 est en héxadécimale et que


0x20 = 32

La taille du fichier vaut un byte (représenté par les 7 derniers bytes) parce que
la valeur 32 est codée sur 8 bits donc 1 byte.

Si on code en texte, on se retrouve par contre avec :

0000000 3332 0000002 cette fois ci la valeur n'est pas la même, tout
simplement parce que ce sont les valeurs unicode de '3' (33) et '2' (32)qui sont
codés dans ce fichier, la taille est plus grande car chaque caractère est codé sur
8 bits (UTF-8).

Il y'a une spécificité par contre dans le codage en texte, en effet quand on code un
caractère spécial (on dira qu'il est étendu, voir Unicode), on verra que la taille pourra
faire par exemple 2 bytes voir plus alors que ce n'est qu'un seul caractère. Prenons par
exemple le caractère œ. Son codage se fera ainsi :

0000000 93c5 00000020

On voit bien que le fichier fait 2 bytes, c'est normal car la valeur 93c5 est codé
sur 2 bytes, mais 93c5 ne correspond pas a la valeur 0153 dans la table unicode
qui correspond a ce caractère. Tout simplement parce qu'on a appliqué un
masque sur le codage de 0153, voici un exemple.

* Le code unicode vaut 0153 ce qui vaut 0000001 01010011 en binaire.


* On applique le masque 110xxx-- 10xxxxxx sur ce codage afin d'obtenir la
représentation binaire en UTF-8 (les – sont la pour signifier que les 2 bits
remplacé par le 10 dans le second byte sont décalés vers la gauche)
* Ceci nous donne 11000101 10010011 en représentation binaire UTF8
* Si on traduit cela en hexa, on obtiens bien c5 93 qui est la représentation en
little indian de 93 c5, mais on dépasse le cadre du cours de Java.
Il est intéressant de noter que les deux représentations se ressemble, en effet, on ne
pourra pas reconnaître un fichier texte d'un fichier binaire rien qu'en regardant le
code, ici c'est facile car c'est un seul caractère, mais sinon il nous faut l'information
afin de pouvoir manipuler correctement ces fichiers

2. les Fichiers

En Java, les fichiers sont considérés comme des flux dans lesquel on pourra lire ou
écrire, ces flux peuvent être binaire ou texte. Ces flux sont uniformes et ils sont non
structurés.

Java fournis des classes de bas niveau pour pouvoir lire/écrire des byte (binaire) et
des char(texte), il existe également des classe de haut niveau qui permettent de
lire/écrire des objets et des lignes entière de texte.

Intéressons nous aux classes de bas niveau. Il y'a 4 classes principales pour les
classes de bas niveau
Byte (8 bits) Char (16 bits
Lire (READ) InputStream Reader
Ecrire (WRITE) OutputStream Writer

Mais il n'y a pas que ces classes, en effet pour chaque classes on aura des sous-
familles comme par exemple FileInputStream ou FileWriter.
Par exemple pour la lecture binaire, on utilisera InputStream qui contiens des
méthodes permettant de lire des bytes. Pour instancier l'InputStream on utilise une
classe utilitaire nommée Files qui contiens une méthode newinputStream qui renvoye
un input stream sur le fichier qu'on veut lire. Cette méthode a besoin d'un Path (voir
l'autre mot IO) et d'une option d'ouverture pour pouvoir ouvrir le fichiers, ces options
sont contenues dans l'Enumeration StandardOpenOption par exemple qui contiendra
READ, APPEND, CREATE ou encore WRITE. Voici un exemple de lecture dans un
fichier binaire :

int b;
try (InputStream in = Files.newInputStream(Paths.get("File"),
StandardOpenOption.READ)) {
b = in.read();
while (b != -1) {
System.out.println(" " + b);
b = in.read();
}
} catch (IOException e) {
System.out.println("problème");
}
On remarque également l'utilisation d'un try with ressources (voir mot clé try) et des
IOException, en effet, on est dans le package java.io et toutes les classes comme
Files, InputStream, IOException, StandardOpenOption en font également partis.

Pour l'écriture binaire dans un fichier le principe est le même sauf que cette fois ci on
utilise OutputStream pour écrire dans un fichier binaire. On utilise également une
méthode des Files qui renvoie un output stream et par contre l'option d'ouverture
change, au lieu de lire on peut créer un fichier pour y écrire ou tout simplement écrire
directement. Voici un exemple :

int b;
try(OutputStream out=Files.newOutputStream(Paths.get("File2"),StandardOpenOptio
n.CREATE)) {
out.write(64);
} catch (IOException e) {
System.out.println("problème");
}

On remarque que int InputStream.read() renvoie un int et OutputStream.write reçois


un int en paramètre alors qu'il traite des bytes. En fait, InputStream.read() renvoie un
int qui correspond au byte qu'il a lus, sachant que sa valeur est entre 0 et 256 (2⁸
valeurs), pour OutputStream.write(), cela correspond a la valeur qu'il doit coder en
binaire par la suite.
Flux d’entrée fichier texte

C’est le même principe que pour les fichiers binaire sauf que les classes sont
différentes parce que on utilise FileReader() pour lire et FileWriter() pour écrire =>
des int également mais lis ou écrit un char

Reader

Base de toutes les classes relatives à des flux texte d’entrée, dotées de fonctionnalités
de base (lecture de caractères et de tableaux de caractères)

int read() // lit un caractère (-1 si fin de flux)


int read(char[] tabChar) /* lit une suite de caractères (au plus b.length)
dans b, fournit le nombre de caractères lus (-1 si fin de flux) */
void close() // ferme le flux

 FileReader

Fichiers texte d’entrée. Cette classe est dotée des mêmes fonctionnalités de base que
Reader.
FileReader(String nomFichier)
FileReader(File objFichier)

 Writer

Base de toutes les classes relatives à des flux texte de sortie, dotées de fonctionnalités
de base (écriture de caractères et de tableaux de caractères).
int write(int n) // écrit le caractère n
int write(char[] tabChar) // écrit le tableau de caractères tabChar
void close() // ferme le flux

 FileWriter

Fichiers texte d’entrée, associé à un fichier.


FileWriter(String nomFichier)
FileWriter(String nomFichier, boolean ext)
FileWriter(File objFichier)
Exemple FileReader

int c;
try (FileReader in = new FileReader("data")) {
while ((in.read()) != -1) {
c = in.read();
System.out.print((char) c);
// il faut faire le cast car ce qui est renvoyé par le flux, c'est un int
}
} catch (IOException IOE) {
System.out.println("salam");
}

Exemple FileWriter

int c = 'a'; // on caste car il a besoin d'un int, mais cela fonctionne si on laisse en char
try (FileWriter out = new FileWriter("fayenafou")) {
out.write(c); // seuls les 2 bits de poids faible sont écris, ceux qui correspondent
//au codage
} catch (IOException IOE) {
System.out.println("salam");
}

31. Scanner/Console

1. Scanner

C’est une classe qui offre plusieurs méthodes de lectures, écritures et de tests. On l’a
très souvent utilisé au tout début de notre apprentissage java en tapant au clavier par
exemple des valeurs, des chaines... Et aussi dans l’écriture d’un fichier Texte ou
binaire. Mais cette classe est beaucoup plus large.
- Premièrement, découper la chaîne de caractères en tokens grâce à un délimiteur ;
Il s'agit par défaut d'un caractère "blanc" (espace, tabulation, retour à la ligne...) ;

- Ensuite, utiliser les méthodes de type hasNext...() et next...() pour parcourir,


récupérer et convertir ces tokens.

Note : lorsque sont retirés les commentaires et espaces, un programme n’est plus
composé que de tokens, qui sont donc les mots ou symboles terminaux du langage.
Elle a fait son apparition dans le package java.util dans la version 1.5.0 de java.

Exemple :
Import java.util.Scanner ;

On doit toujours l’importer car elle ne fait pas partie de java lang.
Ensuite pour l’utiliser à notre gré dans notre classe il faut implémenter un objet de
type Scanner via l’instruction:
Scanner clavier = new Scanner(System.in) ;

Le fait de placer en paramètre le terme System.in indique au compilateur que l’objet


clavier doit scanner le système d’entrée standard, c’est-à-dire le clavier.

Mais d’autres entrées sont envisageables comme par exemple :


Scanner uneEntrée = new Scanner(String unePhrase) ;
Scanner uneAutreEntrée = new Scanner(new File("nomDuFichier")) ;

Utiliser une méthode de la classe Scanner afin de lire une valeur d’un certain type.
unEntier = clavier.nextInt() ; // pour lire un entier

 nextLine() pour les chaines jusqu’à la fin de la ligne, next() prend tous les
caractère qu’on écrit jusqu'au prochain espace ou (retour à la ligne) et retourne un
String constitué de ces caractères.
Exemple j’écris « bonjour ça va ? »
String b = clavier.next();
b = "Bonjour" ; il ne reçoit que le bonjour
Et si j'écris "1"
Il retourne "1" mais en String

 Lors de la saisie d’une valeur ne correspondant pas au type spécifié par la méthode
de lecture, une exception de type java.util.InputMismatchException sera levée.

 Les méthodes de type hasNext...() (hasNextInt(), hasNextFloat()...) fonctionnent


sur le même principe qu'un itérateur, et indiquent si le prochain token existe et s'il est
bien du type spécifié. Une fois cette vérification effectuée, les méthodes de la forme
next...() (nextInt(), nextFloat()...) permettent de récupérer le dit token, directement
converti dans le type adéquat. Un itérateur est en fait un pointeur. On le nomme
itérateur, car sa fonction est d'itérer, c'est-à-dire parcourir une séquence.
 A noter qu'existent également les méthodes simples hasNext() et next(), qui
permettent de savoir s'il existe un token (de n'importe quel type) et de le récupérer
sous forme de String.

Ce qu’on peut faire c’est imposer un schéma de lecture au clavier :

Exemple :
String s = clavier.next(« [HhFf] ») ;

Ce qu’on doit taper c’est que les caractères H,h,F,f sinon InputMisMatchException

2) Exemple :

public class Exemple1 {


public static void main(String[] args) {
String unePhrase = "" ;
Scanner clavier = new Scanner(System.in) ;
unePhrase = clavier.nextLine() ;
System.out.prinln(unePhrase) ;
}
}

Flux standard

Un flux est un élément qui peut fournir ou recevoir une suite d’octets ou de
caractères. Le package java.io fonctionne avec n’importe quel flux, c’est pour cela
qu’il est aussi bien possible d’utiliser Scanner et println avec des fichiers qu’avec
l’écran ou le clavier.
Lorsqu'un programme s'exécute, 3 flux existent automatiquement et à priori
connectés au clavier et à l'écran mais peut être changé via une redirection.
- System.in : l'entrée standard de type InputStream. Classe générale pour un flux
binaire en entrée, FileInputStream hérite d’InputStream.
- System.out : la sortie standard de type PrintStream, ce qui explique l'existence de
println.
- System.err : l'erreur standard aussi de type PrintStream, Flux séparé ce qui permet
de ne rediriger que les erreurs.

System.out.println ?

System est une classe du package java.lang.


Out est un attribut static de la classe System, c'est un type PrintStream : on peut écrire
dessus à l'aide des fonctions print et println qui agissent sur out.
System.out fait référence à la sortie standard du système, qui normalement est l'écran.
2.Console

C'est une classe qui fait partie du package java.io, elle permet un acc§s a la console
du système d'exploitation afin de pouvoir saisir ou afficher des données. Cette classe
fait également usage des flux de type Reader et Writer (vu dans les IO) afin de
pouvoir gérer correctement les caractères.

Pour l'utiliser, il faut donc d'abord l'importer, ensuite en créant l'instance Console de
cette manière :

Console console;

Il faudra également rajouter une méthode qui permettra d'instancier une console, cette
méthode se trouve dans la classe System et se nomme console(). Ainsi quand on
voudra utiliser une console on devra instancier comme cela :

Console console = System.console() ;

Une fois cette étape accomplie, on a accès aux méthodes de la classe Console qui
sont assez classiques. On y retrouvera par exemple readLine() qui se chargera de lire
une ligne à partir de la console ou encore une méthode format() qui est la copie de
String.format() et qui permettra de placer un String dans le message affiché en
fonction de sa valeur. On retrouvera également une autre méthode se nommant
readPassword() permettant de lire au clavier sans afficher les caractère qu'on écris a
l'écran, souvent utilisé pour masquer un mot de passe, d'ou le nom de la méthode.

Cette méthode est donc un bon substitut a Scanner et a l'affichge via System.out, mais
le principal intérêt de la classe c'est que la lecture se fait via la console du système et
non pas depuis un IDE comme Netbeans ! On se rend compte que lorsqu'on essaye de
lancer un programme qui lis ou écris avec Console depuis Netbeans, il y'a une
nullPointerException. La seule manière d'exécuter les programmes qui fonctionnent
avec cette classe, c'est d'utiliser l'invite de commande sur Windows par exemple, ou
celui sur Linux et de lancer les fichiers via une commande java.

Voici un exemple de programme qui fonctionne avec Console.

import java.io.Console;
public class conss {
public static void main(String[] args) {
Console console = System.console(); // on instancie via la méthode console
String name = console.readLine("Enter name");
// ici on a affiché le message en paramètre avant de lire au clavier
console.format("Your name is %s", name);
}}// ici on a affiché le message en remplaçant le %s par le paramètre name
Pour lancer ce programmes voici les étapes :
- Lancer l'invite de commande
- Aller dans le répertoire ou se trouve le conss.java et le conss.class ou juste le .java et
utiliser classpath
- utiliser la commande java conss et le programme se lance

32. Object/Objects

Object/Objects

A. Object

Qu’est-ce que ‘Object’ ?

Object est une classe qui possède comment package java.lang (qui elle-même
contient énormément de class qui sont fréquemment utilisées comme : Math,
String, Enum... et autres).
Etant une classe elle possède donc des attributs et des méthodes, cependant
Object est une classe particulière, on dit qu’elle est la racine de la hiérarchie des
classes, c’est-à-dire que toutes les classes possèdent comme super class, la class
Object et donc ses méthodes, c’est une espèce d’héritage implicite, par défaut
toute classe hérite de Object.

C’est le boss !

Donc écrire :
class Othman extends Object {
// bla bla bla
}

est inutile !

Méthodes d’Object

La classe Object possède plusieurs méthodes, mais voyons 3 intéressantes…


non soyons fou 4 intéressantes.

1 toString ()
2 getClass ()
3 equals (Object o)
4 hashCode ()  si pas alz avec le hashCode ne pas en parler, sauve si le
prof demande…
I. toString()

Entête : String toString()


Paramètre : aucun
Retour : un entier
Rôle : permet d’obtenir un string représentant un objet

Le toString de la classe Object permet de représenter n’importe quel Object


sous forme de chaine de caractère pour pouvoir par exemple l’afficher par un
‘sout’

Soit le classe personne prenant dans son constructeur en paramètre le nom


d’une personne voici un exemple du toString .

public class Test{


public static void main(String args[]){
Personne p1 = new Personne("Omar") ;
System.out.println(p1.toString());
}
}

Le to string ne donne pas toujours une forme que nous souhaitons, la plus part
du temps elle renvoi des caractères peut agréable style
‘Personne@b82e3f203’(le nom de la classe, suivie de ‘@’, et une adresse en
hexadécimal, qui est l'adresse mémoire où l'objet est stocké)
Pour changer cela il faut faire un override de cette méthode. (Redéfinir le
comportement d’une méthode existante de la classe parente)

(cf mot-clé ‘toString() pour plus d’infos :p).

II. getClass()
Entête : public final Class getClass()
Paramètres : aucun
Retour : une instance de la classe Class
Rôle : permet d’obtenir la classe d’un objet

Le getClass de la classe Object donne tout simplement la classe d’un objet


Soit le classe personne prenant dans son constructeur en paramètre le nom
d’une personne voici un exemple du getClass.
public class Test{
public static void main(String args[]){
Personne p1 = new Personne("Omar") ;
System.out.println(p1.getClass());
}
}
> Classe de p1 : class Personne

N.B : A l’affichage on aura le package complet de la classe de p1

III. equals(Object o)

Entête: public boolean equals(Object o)


Paramètres : un objet
Retour : un booléen
Rôle : permet de comparer deux objets

Le equals (Object o) de la classe Object permet de comparer deux classes et


savoir si ils sont égaux, il retourne un booléen indiquant si ils sont égaux ou
pas.
Si on essaie de comparer deux objets avec le ‘== ‘ on obtient toujours false car
en réalité il compare deux adresses qui sont différents. C’est là que nous sauve
le equals qui lui permet de comparer les champs des objets (cf mot-clé ‘equals’
pour plus d’infos :p).
Mais comme la méthode toString cette méthode a souvent besoin d’être
override pour pas se faire bahkar x) . Dans l’override on va comparer chaque
champ de l’objet avec ceux de celui passé en param.

*Le plus chiant pour la fin 


IV. hashCode()
Entête: public final Class getClass ()
Paramètres : aucun
Retour : une instance de la classe Class
Rôle : permet d’obtenir la classe d’un objet

Le hashCode de la classe Object permet d’obtenir le hash code d’un objet qui
est un nombre unique associé à l’instance de cet objet(0 si l’objet est nul), par
défaut il retourne l’adresse ou est stocké cet objet en question, nombre qui sera
unique puis ce qu’on ne peut pas stocker deux objets à la même case mémoire.
Là où ça devient chiant c’est le fait qu’il y a un lien directe entre le méthode
equals et le hash code d’un objet. Car pour la méthode equals () deux objet sont
égaux si ils retournent le même hash code.
Donc faire l’override d’une méthode equals implique l’override de la méthode
hashCode, sinon bonne chance xD !
Faire l’override d’une méthode hashCode() n’est pas facile et doit respecter un
algo bien précis.

B. Objects

Qu’est-ce que ‘Objects’ ?

Hé bien Objects n’est pas ‘object ‘ prononcé à la smex ^^ , c’est bel et bien une
classe à part entière, possédant ces propres attributs et méthodes. Comme toutes
les classes, et expliqué plus haut, elle hérite par défaut de la classe ‘object’
ainsi que de quelques-unes de ces méthodes dont celles parlées plus haut.

Plus spécifiquement Objects est une classe du package java.util, possédant des
méthodes STATIC qui permettent de travailler avec des object. Elle ne peut pas
être instancié, car class final et ne possède pas de constructeur public.

Méthodes d’Objects

Voici 2 méthodes propres à cette classe

I. T nonNull(T obj)
Si l’objet n’est pas nul retourne l’objet sinon lance une NullPointerException.
public void setFoo(Foo foo){
this.foo = Objects.nonNull(foo);
}

II. int compare(T a, T b, Comparator<? super T> c)


C’est une espèce d’equals, retourne 0 si a == b ou si les deux sont null, sinon
retourne c.compare(a, b).

III. Les autres méthodes sont celles héritées par object ou des
améliorations de celles-ci
33. Literal

Qu’est-ce qu’un ‘Literal’ ?

En java tous les éléments se déclarent, et ils se déclarent par des types qu’on appelle
les primitives (cf. mot-clé ‘type primitif vs Référence pour plus d’infos :p).
Un literal c’est tout simplement une valeur constante affectée à un type primitif. Ça
peut donc être : un int, un char, un long, un short…

Voyons un exemple :

Exemple :

int value = 7;
int : est un type primitif (un type de donné)
value : est un nom de variable et une référence
true : est un littéral de type entier (integer literal)
Dans l’exemple ci-dessus '7’ est un literal de type entier auquel on peut accéder par
sa référence ‘value ‘.
System.out.println(value)

Notez cependant qu’un literal peut également être une valeur constante affecté à des
objects tel que ‘String’(ou n’importe quel autres objects), par exemple les string
literal existent.

Pour généraliser ça reprenons le tout dans un tableau

primitif Nom variable/ = Exemple de literal


référence

boolean result = true/false

Char majusculeJ = ‘J’

Byte quatreBin = 100(b)

Short s = 10000

int nb = 100000

En guise de conclusion on peut dire qu’un literal possède un type une valeur et une
référence vers cette valeur.
Mais il ne faut pas se contenter de ces explication et expliquer également les types
primitifs dans le mot clé suivant

34. Type primitif vs Type réference

Chaque donnée en java a un type vu que le langage est fortement typé.

1) Type primitifs

Le langage Java dispose d’un certain nombre de types de base dits primitifs,
permettant de manipuler des entiers, des flottants, des caractères et des booléens. Ce
sont les seuls types du langage qui ne sont pas des classes. Mais ils seront utilisés
pour définir les champs de données de toutes les classes que l’on peut être amené à
créer.

 Les types entiers (byte short int long)

Ils servent à représenter des nombres entiers relatifs.


Un bit est réservé au signe (0 pour positif et 1 pour négatif). Les autres servent à
représenter :

• la valeur absolue du nombre pour les positifs ;


• le complément à deux du nombre, pour les négatifs.
* Les types flottants (double float)

Ils permettent de représenter, de manière approchée, une partie des nombres réels.
Plus précisément, un nombre réel sera représenté en flottant en déterminant un signe s
(+1 ou -1), une mantisse M et un exposant E tel que la valeur s . M . 2^E représente
une approximation de ce nombre.

* Le type caractère (char)

Le langage Java permet de manipuler des caractères représentés en mémoire sur deux
octets en utilisant le code universel Unicode.

* Le type booléen

Ce type sert à représenter une valeur logique du type vrai ou faux. Les deux
constantes du type booléen se notent true et false et sont codées sur un octet.
Chacun des types primitifs peut être "enveloppé" dans un objet provenant d'une
classe prévue à cet effet et appelée Wrapper (mot anglais signifiant enveloppeur). Les
enveloppeurs sont donc des objets représentant un type primitif.

Avantage :

* Les Wrapper peuvent être utilisés comme n'importe quel objet, ils ont donc leurs
propres méthodes.

Inconvénients :

* L'objet enveloppant utilise plus d'espace mémoire que le type primitif. Par exemple,
un int prends 4 octets en mémoire mais un Integer utilisera 32 octets sur une machine
virtuelle en 64 bits (20 octets en 32 bits).
* L'objet enveloppant est immuable, c'est à dire qu'il ne peut pas être modifié, toute
modification de sa valeur nécessite de créer un nouvel objet et de détruire l'ancien, ce
qui augmente le temps de calcul.

Leurs noms = cf. autoboxing

Un nombre entier est un nombre sans virgule qui peut être exprimé dans différentes
bases:31

* Base décimale: (de 0 à 9)


* Base hexadécimale: (de 0 à 9 ou de A à F (ou a à f)) devant commencer par 0x ou
0X
* Base octale: (0 à 7)
Lorsqu'un nombre est trop grand pour être représenté par un int, il faut explicitement
le déclarer comme étant un long en lui rajoutant un L : long n = 9876543210L; // !!
Toujours le L après.

2) type référence

Le nom d'une classe peut être utilisé comme un type, de sorte qu’il est possible de
déclarer une variable de type objet ou spécifier qu'une méthode renvoie un objet. Si
une variable est déclarée en utilisant le nom d'une classe comme type, cette variable
contiendra une référence à un objet de cette classe. Une telle variable ne contient
donc pas un objet réel, mais plutôt une référence à l'instance de classe, ou objet, à
laquelle la variable fait référence.

Puisque l'utilisation d'un nom de classe comme type déclare une référence à un objet,
ces types sont appelés types de référence.

Java permet également l'utilisation d'un nom d'interface pour spécifier un type de
référence. En outre, les types de tableaux (Arrays) sont également des types
référence, car le langage Java les traite comme des objets.

 Chaînes de caractères (String) : Les chaînes de caractères ne correspondent pas à


un type de données mais à une classe, ce qui signifie qu'une chaîne de caractère est
un objet possédant des attributs et des méthodes. Une chaîne peut donc être déclarée
de la façon suivante :

Ex :
String s = "Chaine de caractères"; (sorte de tableau de caractères).

Conclusion :
Type primitif = sa valeur sur la pile
Type référence = l’adresse de l’objet est sur la pile est le contenu de la variable
(objet) est sur le tas.

« Derrière » une variable se cache une petite zone de la mémoire de l’ordinateur dans
laquelle sera stockée la valeur de la variable. Les d´déclarations sont le moyen de dire
à JAVA de réserver une zone pour chaque variable (la taille de la zone d´dépendra du
type de la variable : pour le type char, c’est 1 octet, pour le type int, c’est 4 octets,
pour double, c'est 8 octets…). »
35. toString()

Méthode héritée de la classe Objet en conséquence toutes les classes Java en hérite.
La méthode toString() définie dans la classe Object ne fait pas grand-chose : elle
renvoie le nom de la classe de l'objet concerné suivi de l'adresse de cet objet.
Lorsqu'on écrit une classe, il peut être très utile de redéfini la méthode toString() afin
de donner une bonne description des objets de cette classe. Si on l’a redéfinie (retaper
en fonction de la classe) la méthode toString() en java permet de donner un aperçu
d'un objet instancié. C'est à dire que cette méthode va retourner une chaine de
caractère représentant un objet : affichage de la valeur des propriétés par exemple.
Il est intéressant de noter que le nom de classe est bien le nom de la classe
correspondant à l’objet référencé, même si toString n’a pas été redéfinie. En effet, la
méthode toString de la classe Object utilise une technique dite de "fonction de
rappel". Plus précisément, elle appelle une méthode getClass (introduite
automatiquement par Java dans toutes les classes via le package java.lang) qui fournit
la classe de l’objet référencé sous forme d’un objet de type Class contenant, entre
autres, le nom de la classe.

2) Exemple sans redéfinition

class Point {
private int x, y ;
public Point(int abs, int ord) { // constructeur à 2 paramètres
x = abs ;
y = ord ;
}
}
public class ExempleToString {
public static void main (String[] args) {
Point a = new Point(1, 2);
Point b = new Point(5, 6);
System.out.println("a : " + a.toString()) ;
System.out.println("b : " + b.toString()) ;
}
}

a : Point@fc17aedf
b : Point@fc1baedf

3) Exemple Méthode toString redéfinie dans la classe Point.

public String toString() {


return "abscisse = " + x + " ordonnée = " + y ;
}
a : abscisse = 1 ordonnée = 2 et b : abscisse = 5 ordonnée = 6
36. Collection/List

1) List dans le langage java

Les objets appartenant à la catégorie List sont, pour simplifier, des tableaux à
agrandir à l’infinie. On y trouve les objets Vector (jamais vu), LinkedList et
ArrayList. On peut y insérer autant d'éléments que l’on le souhaite sans craindre de
dépasser la taille de notre tableau. Ils fonctionnent tous de la même manière : on peut
récupérer les éléments de la liste via leurs indices. De plus, les List contiennent des
objets. Un indice géré par l’interpréteur permet de retrouver l’information.
Indépendamment de cet ordre naturel, on pourra, dans certains cas, avoir besoin de
classer les éléments à partir de leur valeur. Lorsqu’il est nécessaire de disposer d’un
tel ordre sur une collection, les méthodes concernées considèrent par défaut que ses
éléments implémentent l’interface Comparable (java.lang.Comparable) et recourent à
sa méthode compareTo.

Les données enregistrées dans une ArrayList sont en réalité rangées dans un tableau
interne créé par l’interpréteur. La taille de ce tableau est gérée automatiquement par
Java. Ainsi, lorsque la liste des éléments à ajouter dépasse la taille du tableau interne,
un nouveau tableau est créé et les anciennes valeurs y sont copiées.

- Avantage : fonctionnalités d’accès rapide (lecture).


- Inconvénient : lacune inhérente à sa nature : addition et suppression d’un objet à une
position donnée peu efficaces. La vitesse d’exécution dépend de la position à laquelle
il faut ajouter ou supprimer un objet.

Implémentation :

ArrayList<T> liste = new ArrayList<T>() ;

Tous les éléments d’une même liste sont donc de même type T.
Ainsi déclaré, liste est un objet de type ArrayList, auquel on peut appliquer des
méthodes de la classe ArrayList :

Methodes :
Ajout de l'élément de valeur 1 : .add(1) ;
La taille de la liste : .size() ;
Vrai si la liste est vide : .isEmpty() ;
Accès au 11ème élément : .get(10) ; // car ça commence a 0
Remplacement du 11ème élément par la valeur 3 : .set(10,3) ;
Vrai si la liste contient la valeur 3 : .countains(3) ;
Indice de la première occurence de l'élément 3 dans la liste : .indexOf(3) ;
Suppression de l'élément en 11ème position : .remove(10) ;
suppression du premier élément de valeur 3 : .remove(new Integer(3)) ;
L'objet ArrayList

Voici un objet bien pratique. ArrayList est un de ces objets qui n'ont pas de taille
limite et qui, en plus, acceptent n'importe quel type de données, y compris null ! Nous
pouvons mettre tout ce que nous voulons dans un ArrayList. Elle est plus rapide pour
accéder à un élément.

On utilise toujours l’interface List = implémenter par ArrayList et LinkedList, elle


définit les méthodes pour les listes (cf. interface).

Déclaration et création d’une liste.

List <String> maListe = new ArrayList <String> () ;


Seul les objets sont permis dans les listes je ne pourrais avoir une liste de int mais une
liste de Integer (wrapper cf. Autoboxing) qui enveloppe une valeur primitives dans un
objet.

Pour parcourir une liste et l’afficher on procéde comme cela :

For (int i = 0 ; i<liste.size() ; i++){


System.out.println(liste.get(i)) ; // get(i) permet d’acceder a l’élement à la pos i
}

L'objet LinkedList

Une liste chaînée (LinkedList en anglais) est une liste dont chaque élément est lié aux
éléments voisins par une référence à ces derniers. Chaque élément contient une
référence à l'élément précédent et à l'élément suivant, excepté le premier, dont
l'élément précédent vaut null, et le dernier, dont l'élément suivant vaut également
null. Plus rapide quand on ajouter au début.
Implémentation :

LinkedList<T> liste = new LinkedList<T>() ;

- Avantage : permet des ajouts et des suppressions à une position donnée en un temps
contant quelques soit la position.

- Inconvénient : l’accès à un élément (lecture) dans la liste sera peu efficace puisqu’il
nécessitera obligatoirement de parcourir une partie de la liste.

 Classe Collection

On utilise aussi des methodes STATIC de la classe Collection pour manipuler nos
listes. Pour l’utiliser, un import est obligatoire :
import java.util.Collections ;

Elle offre les méthodes de classe suivantes pour une liste d’entiers :
- pour obtenir l'élément maximum de la liste : Collections.max(liste) ;
- pour trier la liste : Collections.sort(liste) ;
- pour inverser la liste : Collections.reverse(liste) ;
- pour mélanger la liste : Collections.shuffle(liste) ;

 La méthode compareTo()

La méthode compareTo() doit renvoyer :


- une valeur entière négative si l'objet courant est inférieur à l'objet fourni ;
- une valeur entière positive si l'objet courant est supérieur à l'objet fourni ;
- une valeur nulle si l'objet courant n’est égal à l'objet fourni.

 Attention :

Sachant que .get(0) représente le premier élément d’une liste, l’accès au nième
élément s’écrit .get(n). L’indice de la liste et varient donc entre 0 et .size() - 1. Utiliser
un indice n supérieur à .size() - 1 générera une erreur d’exécution du type :
java.lang.ArrayIndexOutOfBoundsException
2) Exemple :

import java.util.ArrayList ;

public class Exemple1 {


public static void main(String[] args) {
ArrayList<Integer> liste = new ArrayList<Integer>() ;
liste.add(12) ;
liste.add(47) ;
for(int i = 0 ; i < liste.size() ; i++){
System.out.print(liste.get(i) + " ") ;
System.out.println() ;
}
}

Va afficher 12 47

37. Equals

L'opérateur == vérifie que deux objets possèdent la même référence mémoire et sont
donc en fait le même objet. Il va de soi que deux objets identiques sont égaux mais,
deux objets de références mémoire différentes peuvent également être égaux. C’est
une méthode d’Object qui permet de comparer deux objets entre eux (ou, plus
précisément, elle vérifie que les deux références d'objet sont identiques si ils ont le
même contenu en fait). L'utilisation de cette méthode n'est pas aussi simple que cela,
car elle est implémentée de manière très différente au sein de plus de 150 classes
différentes sur l'ensemble de l'API Java. On peut dire tout simplement que equals()
permet de comparer deux objets, si tant est que ces objets implémentent cette
méthode.

La redéfinition de la méthode equals() permet de fournir des règles particulières pour


le test d'égalité des objets d'une classe. Dans ce cas, son implémentation utilise
généralement un test d'égalité reposant sur tout ou partie des attributs de la classe qui
sont pertinents pour sa discrimination.
Etant donné que String est un type référence on ne compare pas 2 chaines comme si
c’était des types primitifs en utilisant l’opérateur == car on doit comparer leur
référence afin de voir si ceux-ci pointe sur ma même valeur vue que pour les types
référence, la valeur se trouve dans le tas et l’adresse sur la pile.

Exemple page suivante


public boolean equals(Point p) {
return ((this.x == p.x) && (this.y == p.y)) ;
}
True

class Point {
private int x, y ;

public Point(int abs, int ord) { // constructeur à 2 paramètres


x = abs ;
y = ord ;
}
}

public boolean equals(Point p) {


return ((this.x == p.x) && (this.y == p.y)) ;
} –-> Doit retourner True

public class Exemple1 {


public static void main (String[] args) {
Point a = new Point(1,2);
Point b = new Point(1,2);
System.out.println(a.equals(b)) ;
}
} → Va afficher false

38. Unicode – UTF8 – UTF16 - UTF32

L'Unicode est un standard informatique qui permet des échanges de textes dans
différentes langues, à un niveau mondial. Il permet le codage de texte écrit en
donnant à tout caractère de n'importe quel système d'écriture un nom et un identifiant
numérique, et ce de manière unifiée, quelque soit la plateforme informatique ou le
logiciel.

Bien que l'Unicode ait été conçu sur le modèle du jeu de caractère ASCII, il va bien
au-delà des capacité rudimentaires d'ASCII qui ne code que les majuscules et
minuscules de A à Z et qui est codé sur 7 bits. Unicode permet de tous coder, tout les
caractères utilisés par toutes les langues écrite dans le monde cela fait + d'un million
de caractère.
Le codage de caractère Unicode traite les caractère alphabétique, les caractères
idéographiques et les symbole de manière équivalente avec comme conséquence que
tous les caractères peuvent se côtoyer dans n'importe quel ordre avec la même
facilité.
En Unicode, chaque caractère a une valeur numérique et un nom comme tous les
normes de codage qui le précèdent. Cependant, l'unicode fournit d'autres informations
afin de s'assurer que le texte soit lisible, le dévloppement de mise en œuvres
cohérentes et l'échanges de données unicode.

En d'autres termes, Unicode donne un code qui sera unique pour chaque caractère.
Mais on n'utilise différents codage comme UTF-8, UTF-16 et UTF-32 pour pouvoir
représenter ces codes sur + ou – de bits.

Pour représenter un caractère unicode on utilise la norme suivante, on prend le code


hexa de la valeur Unicode (en UTF) et on la fait précéder de \u, lorsqu'on n'est pas en
java, on voit souvent qu'elle est représentée comme U+FFFF par exemple. Donc \u et
4 digit, nous verrons par la suite pourquoi 4 digit

Parlons maintenant des codage UTF-8, UTF-16 et UTF-32.

UTF8 est un codage de caractère informatique conçu pour coder l'ensemble des
caractères du « répertoire universel de caractère codés ». En UTF-8 le nombre de
bytes utilisés varie de 1 à 4. C'est un codage très utilisé et nous l'avons par exemple
utilisé pour pouvoir introduire les accents dans notre commande javadoc sur Linux.

Ex : le caractère € est le 8365ème caractère du répertoire unicode. Tout caractère


ASCII se code en UTF-8 sous forme d'un unique octet identique du code ASCII,
sachant que les 7 bits ASCII seront précédés d'un bit nul pour former l'octet.

Si on code sur un octet le caractère codé peut aller de 0x00 à 0x7F (en hexadécimal),
soit 128 caractères, comme en ASCII.

La représentation sera du type : 0nnnnnnn sachant que n peut être 0 ou 1.

On pourrait également coder sur 2,3 ou 4 octets, les valeurs iront pour 2 octets de
0x0080 (soit 128) à 0x0FFF (soit 4095). Pour savoir sur combien de bit un caractère
doit être codé on s'aide de l'information donnée par les bits de poids fort pour préciser
le nombre de byte utilisé.

La représentation sera du type 1110 0000 101nnnnn 10nnnnnn (on applique une sorte
de masque sur le codage en binaire de 8365) pour € qui est codé sur 3 octets, malgré
le fait que 8365 soit possible a coder sur 2 bit la codification pour UTF-8 a besoin de
14 bits donc 3 octets.

UTF16 est un codage de caractère ou chaque caractère est codé sur une suite de un ou
2 mots de 16 bits. Le numéro de chaque caractère est repris à l'identique par le
standard Unicode ( on va de 0x0000 à 0x10FFFF). C'était dans la version originale de
l'Unicode, mais dans sa nouvelle version, c'est sur 21 bits.
UTF32 est utilisé lorsque la place mémoire n'est pas un problème et que l'on a besoin
d'avoir accès a des caractère de manière directe et sans changement de taille

Maintenant voyons voir l'utilisation d'Unicode en Java. Pour représenter les char,
Java n'autorise que les caractères qui sont compris entre U+0000 et U+FFFF ce qui
correspond a la taille du char (qui est codé sur 2 bytes, donc on utilise UTF-16)
Unicode a depuis accrus le nombre de caractère possible a coder et utilise maintenant
une plus grande palette de codes différents, on code de U+0000 à U+10FFFF.

On comprends dès lors pourquoi on utilise 4 digit lors de la représentation en Java,


chaque digit représente 4 bit comme en hexadécimal, 4*4 = 16 et un char est bien
codé sur 16 bits en java.

Pour la représentation des String, Java utilise les caractère pour les représenter, il
y'aura deux manières. Lorsqu'un caractère est un caractère de base qui est codé sur 16
bits donc 2 bytes, on utilise un char. Lorsque c'est un caractère étendu, Java utilisera 2
char.

Ex : Caractère « clé de sol » qui est U+1D11E. Pour pouvoir le représenter dans un
String (on pourra pas le coder dans un char, vu que c'est un caractère étendu, il lui
faut 2 char), on doit faire une manipulation.

* On enleve 0x10000 au code

0x1D11E – 0x10000 = 0xD11E

* On convertis en binaire et on sépare les 10 bits de poids faible et les 10 bits de


poids fort

0000110100 0100011110

* On ajoute la valeur 0xD800 aux bits de poids fort

0xD800 + 0x34 = 0xD834

* on ajoute la valeur 0xDC00 aux bits de poids faible

0xDC00 + 0x11E = 0xDD1E

On pourra donc représenter le caractère comme

String s = ''\uD834\uDD1E'' ;
Malgré tout, ça ne veut pas dire que le caractère va s'afficher a l'écran, en effet, cela
dépends d'autres choses qui ne sont pas liés au java :)
39. Polymorphisme

Le polymorphisme est le second principe de l'orienté objet.


Poly : plusieurs
morphisme : forme

En java, le polymorphisme est l’aptitude d'un objet à prendre plusieurs forme.


L'utilisation la plus courante du polymorphisme est lorsque on utilise une classe
parente pour référencer une classe fille.

On essaye de ne pas melanger l'overloading qui est la surcharge de methode et


l'overrriding qui nous interesse dans notre cas.
L'overriding est le fait de specialiser une methode de la classe mere dans la classe
fille. La methode doit avoir le meme signature donc meme nom et meme param.

Exemple :

ArrayList<EtreHumain> tab = new ArrayList<>() ;


tab.add(new Homme()) ;
tab.add(new Femme()) ;

L'ArrayList est de type tableau EtreHumain mais je peux y ajouter des objets de type
Homme et Femme ( qui sont aussi des etres humains )

Lorsque on affecte à une variable de type superclasse une variable de type sous classe
, ça ne pose pas de probleme au compilateur. On peut donc mettre des femmes dans
un tableau d'EtreHumain.

Pour vous expliquez ce que le polymorphisme , je vais créer une classe EtreHumain :

Class ettreHumain{

public void uriner(){


sout (« parterre ») ;
}

Et aussi deux classes : Homme et Femme qui herite de EtreHumain

public class femme extends etrehumain{


public void uriner(){
sout(« assis ») ;
}
}
public class homme extends etre humain{
public void uriner(){
sout(« debout ») ;
}
}

Comme vous avez pu remarqué j'ai reécris la methode cheveux pour les deux classes
car bon une femme sa pisse assis et un homme sa pisse debout sauf les zwet

Mnt , on declare dans un main , un tableau comme citée plus haut :

public static void main (String[] args){


ArrayList<EtreHumain> tab = new ArrayList<>() ;
tab.add(new Homme() ) ;
tab.add(new Femme() ) ;
tab.add(new Femme() ) ;
tab.add(new Homme() ) ;

for (EtreHumain etreHumain : tab ){


etreHumain.uriner() ;
}
}

J'ai declarer une arrayList d'EtreHumain et j'y ai rajouté des hommes et des femmes.
Ensuite j'applique la methode uriner sur tout les objets de la liste etreHumain.cheveux
Alors à votre avis , quel methode sera utiliser ? Celle de la classe etreHumain ou celle
des classes homme et femme ?

De quoi vous aidez :

Personange unPersonnage = new Guerrier(…) ;


unPersonnage.rencontrer(unAutrePersonnage) ;
Quel methode utiliser ? La methode rencontrer de la classe Personnage ou celle de
Guerrier ?

Resolution statique des liens :


Le type de la variable sur lequelle est invoquer la methode qui est utiliser pour savoir
quel methode choisir

dans notre cas le type est Personnage donc la methode rencontrer qu'on va utiliser est
la methode rencontrer de Personnage,

Cette resolution n'est pas utiliser en java.


Resolution dynamique des liens :

on va considerer que c'est le type de l'objet stocker dans la variable qui va etre utiliser
pour choisir la methode à appliquer.

Dans notre exemple, on a un type personnage mais qui continent une reference à un
objet de type guerrier. On va donc choisir la methode rencontrer de guerrier.

On parle de resolution dynamique car ce choix va etre fait pendant l'exution du


programme.

En java , on a pas le choix c'est la resolution dynamique qui est utiliser.

40. I/O(Path, Flux Englobant)

1. Path

Un fichier est identifié par son chemin a travers le filesystem via son nom
completement qualifié (aussi nommé FQN) et son Path qui signifie chemin.

Voici des exemple de chemins pour des fichers :

C:\Users\Nasreddine\CurryKetchup.java –--> Windows

/fakir/changementDeVie/vietvodao –--> Linux

On voit déjà que le séparateur est différent en fonction de l'OS. On aura \ pour
Windows et / pour Linux. On sais qu'un path peut être relatif (a partir de l'endroit
courant) ou absolu (a partir de la racine, chemin qui fonctionnera dans tout les cas).

En Java, on représente cela par l'interface Path qui va représenter un chemin et


permettre de le manipuler, on pourra par exemple créer un path, utiliser l'information
contenue dans un Path, convertir un Path, comparer deux path etc.

On utilise la classe utilitaire Paths pour créer un Path a partir de l'interface. Cette
classe appartiens au package java.nio

Exemple :

Path path1 = Paths.get(''/home/zekh/pecs.java'');

Un fichier que représente le chemin peut ne pas exister (ici, on sait tous qu'il existe
hn).

On peut donc utiliser les informations contenues dans un path via plusieurs méthodes
par exemple pour le path :

Path path = Paths.get(''/hmido/déménagement/305.txt'') ;

path.toString donnera /hmido/déménagement/305.txt


path.getFileName donnera 305
path.getParent donnera /hmido/déménagement
path.getRoot donnera /

Les conversions de Paths sont multiple, on peut convertir en URI (uniform ressource
identifier), en chemin absolu, en chemin réel (comme chemin absolu, mais si c'est un
lien, alors ça donnera le path du fichier d'origine) et on pourra également résoudre un
chemin sur base de deux chemins incomplets.

Pour transformer un Path en URI on utilise la méthode toUri de Path, cela


transformera le chemin dans cette norme là.

Exemple :

Path path = Paths.get("C:\\othman\\viveLeCobol");


System.out.println(path.toUri());

affichera file:///C:/othman/viveLeCobol

Pour transformer en chemin absolu on utilisera la méthode toAbsolutePath() qui


partira de la racine par exemple

Path path = Paths.get("khalidou");


System.out.println(path.toAbsolutePath());

affichera /home/hmido/projetRachat/khalidou

Pour transformer en chemin réel même résultat que pour toAbsolutePath(), si ce n'est
pas un lien, si sa en est un,il est remplacé par le chemin vers lequel il pointe

Path path = Paths.get("khalidou");


System.out.println(path.toRealPath());

Il existe également la méthode Path.resolve qui permet créer un chemin sur base de
deux chemins différents.

Par exemple

Path path = Paths.get(''/home/kamel'') ;


Path path2 = path.resolve(''avocat'');
pour retrouver comme path2 /home/kamel/avocat

2.Flux englobant

Dans les exemples vu pour l'écriture dans des fichiers , la lecture et l’écriture est prise
en charge par l’os mais il y a des risques de lenteurs et java propose de buffériser ses
flux (stream). C’est-à-dire qu’un flux lit dans un buffer, lorsque le buffer est vide
l’API est appelé pour une lecture qui va remplir le buffer. Ces flux rentrent dans une
catégorie de flux nommée Flux Englobant. Ils sont utilisés pour la lecture et l'écriture.

Il existe 4 flux pour buffuriser : BufferedInputStream, BufferedOutputStream,


BufferedReader et BufferedWriter.
Un tampon (buffer) est un emplacement mémoire qui sert à optimiser les échanges
avec le flux. Les informations sont d’abord enregistrées dans le tampon, et ce n’est
que lorsque ce dernier est plein qu’il est «vider» dans le flux. Lorsqu’un flux est doté
d’un tampon, sa fermeture (close()) vide tout naturellement le tampon dans le flux.
On peut aussi provoquer ce vidage à tout moment en recourant à la méthode void
flush().

On remarque également que l'utilisation de ces flux rajoute certaines méthodes


intéressantes, comme celle du BufferReader.readLine qui permet de lire une ligne
alors que normalement c'est caractère par caractère pour les Reader. On pourra aussi
écrire un String ou la partie d'un String grâce a la méthode BufferWriter.write()

BufferedInputStream et BufferedOutputStream

. Utilise une zone tampon pour la lecture/écriture


. Optimisation des opérations (rapidité)
. Permet de revenir en arrière

BufferedWriter

Permet de doter un flux texte de sortie(out) d’un tampon.

Voici les constructeur pour créer cet objet :

BufferedWriter(Writer out)
BufferedWriter(Writer out, int taille tampon)

Dans un cas on précise la taille du tampon, dans l'autre cas non, mais pour la plupart
des utilisation, c'est bien assez.

BufferReader
Permet de doter un flux texte d'entrée d'un tampon

Voici les constructeur pour créer cet objet :

BufferedReader(Reader in)
BufferedReader(Reader in, int taille tampon)

Même chose pour la taille du tampon, la plupart du temps c'est bien assez.

Exemples :

BufferedReader inputStream = new BufferedReader (new FileReader (« input.txt ») ;


BufferedWriter outputStream = new BufferedWriter (new FileWriter (« output.txt ») ;
Il y'a également des cas où l'on doit écrire autre chose que des bytes ou des caractères
dans les fichiers binaire ou texte.Pour écrire des données primitives (int char double)
ou String sur un fichier binaire on utilise DataOutputStream. Pour la lecture
DataInputStream, ce sont deux classe étant également utilisé dans le cadre des flux
englobant. Elles contiennent chacune beaucoup de méthodes qui concernent l'écriture
des char, byte, double, int, long et autres données primitive via les méthodes
writeDouble(double v) pour DataOutputStream ou encore byte readByte() pour
DataInputStream. A noter qu'on pourra également lire des String ou les écrire.

Exemple DataOutputStream:

Try (DataOutputStream out = new DataOutputStream (new FileOutputStream (« data


»))) {
Out.writeInt(16) ;
Out.writeUTF(« hello » ;)
}catch (IOException IOE){
//gerer
}

Exemple DataInputStream:

Try(DataInputStream in = new DataInputStream ( new FileInputStream (« data»))) {


Int nb = int.readInt() ;
String titre = int.readUTF() ;
}catch (IOException IOE){
//gerer
}

Lance une EOFException si tentative de lecture au-delà de fin du fichier, pas besoin
de valeur sentinelle du genre 'on lis rien donc on s'arrête', ça s'arrêtera si on met un
catch pour attraper EOFException et le try with ressources fermera de toute façon les
flux. Il faut savoir qu'EOFException hérite de IOException, du coup les exemple au
dessus sont valable.

Maintenant voyons voir les cas ou l'on veut lire ou écrire des données primitives dans
un fichier texte. Il y'a deux manières de lire des données primitives dans les fichiers
textes.

On peut procéder par une combinaison BufferReader et conversion en passant par les
Wrapper Integer, Boolean ou Double par exemple.

Try (BufferedReader in = Files.newBufferedReader(Paths.get(''file''))) {


int i = Integer.parseInt(in.readLine()) ;
System.out.println(i) ;
} catch(IOException e) {
system.out.println(''que des délinquant dans la street'') ;
}

Par contre, le soucis proviens quand on lis quelque chose qui n'est pas un int. Il y'aura
une InputMismatchException donc a utiliser seulement quand on est sûr de soi ou un
seul type de donnée primitive dans le fichier, dans l'autre cas il existe la lecture via la
classe Scanner.

En effet, comme on l'a toujours fait, on a lus des entiers au clavier, mais on peut aussi
lire depuis un fichier sans soucis, le constructeur de Scanner le permet (voir
Scanner/Console).

Exemple :

try (Scanner scanner = new Scanner(Paths.get(''file''))) {


int i = scanner.nextInt() ;
sout (i) ;
} catch (IOE e) {
sout (j'ai la flemme d'écrire sout et de mettre des '') ;
}

Par contre on aura le même soucis avec les MismatchException

Pour écrire dans les fichiers texte des données primitives, on utilise printWriter qui
est également un flux englobant

PrintWriter
Flux texte de sortie(out), propose les méthodes println, print et printf (pour formater
comme String.format() ;
PrintWriter(OutputStream fluxSortie)
PrintWriter(Writer fluxTexteSortie)
void print(String texte)
void println(String texte)

Exemple :

try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(Paths.get(''file''),


StandardOpenOption.CREATE))) {
out.println(10) ;
out.print(''fayen'') ;
out.printf(''billel est un %s'', ''rageux'') ;
} catch (IOException e) {
sout ('' j'aime pas les IO mec'') ;
}

Les deux sujets sont très liés, si vous parlez de l'un vous devrez parler de l'autre c'est
obligatoire, surtout pour l'écriture dans les fichiers qui reviens pour les primitifs ainsi
que le concept de Path qui reviens tout le temps quoiqu'il arrive.

Vous aimerez peut-être aussi