Concepts clés de Java : Interfaces et Héritage
Concepts clés de Java : Interfaces et Héritage
Sommaire:
1. Vocabulaire :
2. Interface :
2.1. Définition
2.2. Syntaxe
2.3. Utilité :
3. Extends
3.1. Définition :
3.2. Exemple :
4. While/Do while:
4.1. While:
4.1.1. Grammaire:
4.1.2. La base:
4.2. Do while:
4.2.1. Grammaire:
4.2.2. La base:
5. (Array)List:
5.1. Avant propos:
5.2. List :
5.2.1. Méthodes générales:
5.2.2. Quelques méthodes du contrat List :
5.3. ArrayList :
5.4. LinkedList :
5.5. ArrayList VS LinkedList:
6. Visibilité :
6.1. Private :
6.2. Public :
6.3. Protected :
6.4. Package :
6.5. Intérêt ?
7. Encapsulation:
7.1. Définition :
7.2. Exemple :
7.3. Explication:
8. Assignation:
11. Tableau 2D :
12. [Link]/out/err :
12.1. L’attribut in
12.2. L’attribut out
12.3. L’attribut err
15. If:
15.1. Grammaire :
15.1.1. if (Expression) Statement
15.1.2. If Then Else Statement
15.2. Les accolades:
15.3. Le dangling
15.4. Différents types:
18. Trier
19. toString:
19.1. Pourquoi toString() et pas [Link]() ?
21. this/super:
21.1. This:
21.2. Super:
22. Throw(s):
22.1. Throw
22.2. Throws
22.3. RuntimeException
22.4. En résumé
24. Filtrer(fonctionnel):
24.1. Le Stream:
24.1.1. Création d’un stream:
24.2. Les opérations intermédiaires(Filter):
24.3. Les opérations Terminaux:
24.4. itérer:
26. Break/Continue:
26.1. Label:
26.2. Break:
26.3. Continue:
30. Polymorphisme :
31. For:
32. Constructeur:
32.1. Getter :
32.2. Setter :
33. Object:
34. Objects :
34.1. deepEquals:
34.2. compare:
34.3. hash:
34.4. isNull / nonNull:
35. Switch:
35.1. La base:
35.2. Syntax of switch case:
36. Path:
37. Collection(s):
39. Enumération:
39.1. De quoi s’agit-il ?
39.2. Normes d’écriture
39.3. Utilisation
40. Hashcode():
41. Equals:
41.1. De quoi s’agit-il?
41.2. Conventions/Utilisation
41.3. Exemple :
42. Static :
42.1. De quoi s’agit-il?
42.2. Attributs static
42.3. Méthode static
42.4. Constructeur static
42.5. Import static
43. Import:
43.1. De quoi s’agit-il ?
43.2. Grammaire
43.3. Import static
44. Sérialisation :
44.1. Introduction
44.2. Serialisation d’un objet :
44.3. Désérialisation :
47. Consignes :
47.1. Modules:
47.1.1. Code Blocks :
47.1.2. Table des matières :
47.2. Répartition :
Expression
Declaration
Assignation
Wrapper
Primitif
Priorités des opérations
2. Interface :
2.1. Définition
Type référence similaire aux classes, elle a la particularité d’être totalement abstraite.
Par conséquent, toutes ses méthodes sont implicitement abstraites. (pas besoin de rajouter le
mot-clé abstract).
Le principal objectif d’une interface est de définir un contrat. Celui ci consiste en un
ensemble de méthodes où ne sont écrites que les entêtes de celles ci. La définition du code
des méthodes de l’interface est la responsabilité de la classe qui va implémenter celle ci.
⚠ Les champs (attributs) ne peuvent être que static et final. Une interface ne peut posséder
de constructeur. Elle ne donc peut être instanciée.
( Les champs sont les membres qui permettent de stocker des valeurs de types de base ou des
objets. )
Une classe implémentant une interface doit implémenter (définir le code de) chaque
méthode de l’interface (elle peut cependant en rajouter). Pour implémenter une méthode il
@Override //facultatif
public void rollingStone(String name) { //attention à définir la
visibilité
[Link] ("Angie...");
[Link] (name);
}
Plusieurs classes peuvent implémenter une interface et une classe peut implémenter une ou
plusieurs interfaces. Une interface peut également étendre une autre interface ( hériter d’une
interface mère).
2.2. Syntaxe
On déclare une interface comme on le fait pour une classe sauf qu’on remplace class par interface.
Pour indiquer qu’une classe implémente une autre il faut, à la suite de public class maClasse,
indiquer implements monInterface.
Comme l’héritage multiple est interdit en java, une interface ne peut étendre qu’une seule
autre interface.
Une classe qui implémente une interface possède toutes les méthodes et attributs de
l’interface implémentée.
2.3. Utilité :
Le polymorphisme
L’intérêt d’une interface est que son code n’est pas défini. Par conséquent, on va pouvoir
avoir plusieurs classes implémentant une interface et chacune des classes implémenetra
différemment la dite interface. Chaque classe ayant les mêmes en-têtes de méthodes, on va
donc pouvoir les appeler de la même manière.
On souhaite représenter une série d’armes qui font des dégâts différents ou qui ont des
effets différents.
Pour cela on crée une interface Arme. Chaque classe représentant une arme devra
alors implémenter Arme. Une lance empoisonné pourrait alors définir une méthode attaque
comme infligeant 5 points de vie à la cible et chaque tour, draine la vie de la cible de 1 point.
Une attaque d’une hache pourrait infliger 10 points de dégâts et étourdir la cible.
Imaginons maintenant que notre arme puisse aussi être aussi un objet de soin (un sceptre par
exemple), il suffit d’implémenter dans la classe Sceptre, Arme et ObjetSoin(interfaces). Ainsi
le sceptre pourra utiliser la méthode attaquer() de Arme et la méthode soin() de ObjetSoin.
Et ceci n’aurait pas été possible avec une classe abstraite simple car une classe ne peut hériter
que d’une classe à la fois (pas d’héritage multiple).
3. Extends
3.1. Définition :
Le mot extends est un mot clé de java qui définit qu’une classe hérite d’une autre.
Une classe Enfant hérite d’une classe Parent -> Enfant extends Parent
La classe enfant qui hérite, récupère les attributs et les méthodes de la classe parents.
3.2. Exemple :
Une classe Pion.
Un point est définit par une valeur de x et de y dans un plan. Nous pouvons choisir que certains pions
ont aussi une couleur. Nous créeront la classe PionColoré qui héritera de la classe Pion. Un pion
coloré aura donc une valeur x, une valeur y et une couleur car x et y sont hérité. Idem pour les
méthodes
L’héritage multiple est illégal en java. On ne pourra donc pas avoir un Enfant avec deux
Parents. Pour palier à ce problème on va utiliser des interfaces.
4.1. 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.
4.1.1. Grammaire:
La boucle while sera exécutée par le résultat de l’Expression. Si le résultat est de type
Boolean (avec grand B!) alors il est sujet à la conversion de son type référent
(Wrapper → primitive type, cela signifie simplement que Boolean (wrapper) devient
boolean (primitif) ⇒ unboxing en termes java).
CONDITION D’ARRET:
○ Si la valeur est false alors aucune action du Statement est exécuté et la boucle
while s’arrête correctement.
Il est possible d’émuler (simuler) un for avec un while en respectant cette grammaire
init
while(Expression){
Statement
Update
}
En déclarant et assignant une valeur i (par exemple) avant le while et en mettant à jour cette
valeur dans la boucle; lors de l’évaluation de l’Expression (si “i” en fait parti) on peut
reproduire le comportement du for. Cela est pratique lorsqu’on parcourt un tableau par
exemple à l’aide d’un while .
Si il y a une incrémentation, elle 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.
Contrairement au for, la déclaration de la variable qui s'incrémente ne se fait pas dans la
boucle while mais avant.
4.1.2. La base:
Une boucle commence par l'utilisation du mot clef, ici : while. Cela veut dire, « tant que ».
Puis nous avons une condition : c'est elle qui permet à la boucle de s'arrêter. Une boucle n'est
utile que lorsque nous pouvons la contrôler, et donc lui faire répéter une instruction un certain
nombre de fois. C'est à ça que servent les conditions. Contrairement au for il est utilisé
lorsqu'on veut arrêter le traitement à un moment donné mais qu'on ne connait pas le nombre
d'itération à l'avance. Ensuite nous avons une ou plusieurs instructions : c'est ce que va
répéter notre boucle (il peut même y avoir des boucles dans une boucle).
On quittera le while q uand la condition ne sera plus respectée.
On peut effectuer le même traitement qu'un for avec un while en utilisant cette grammaire.
4.2. Do while:
4.2.1. Grammaire:
do Statement while ( Expression );
Le do while fait au moins une itération avant de vérifier la condition.
4.2.2. La base:
C’est un r épéter tant que. Le do while s’exécute au moins une fois.
Il effectue une fois puis fait le test ,donc au moins un tour de boucle puisque le test se fait
après.
Première différence
La boucle do… while s'exécutera au moins une fois, contrairement à while. C'est-à-dire que la
phase de test de la condition se fait à la fin, car la condition se met après le while.
Deuxième différence
C'est une différence de syntaxe, qui se situe après la condition du while. Il y a un « ;» après le
while. C'est tout ! Ne l'oubliez cependant pas, sinon le programme ne compilera pas.
Mis à part ces deux éléments, ces boucles fonctionnent exactement de la même manière.
Exemple :
int i = 9 ;
do {
int nb;
do {
nb = clavier . nextInt ();
} while (nb<=0);
Les conditions d’arrêt d’un boucle do...while sont les mêmes que celle de la boucle while.
5. (Array)List:
5.3. ArrayList :
Implémentation de l’interface List. L’arrayList a pour particularité d’être en fait un
tableau. Au début, la taille de ce tableau est de 10 et il ne contient rien. Ensuite quand on
souhaite ajouter un éléments, on crée un nouveau tableau d’une taille qui est double par
rapport à la taille de l’ancien tableau, on mets les éléments de l’ancien tableau dans le
nouveau tableau et finalement on rajoute le dernier élément.
Par conséquent, plus on va ajouter d’éléments plus la taille du tableau de notre List
sera grande. Si on ajoute un élément à une arrayList dont la taille du tableau est 5000 et que
toutes les 5000 cases du tableau sont occupées, on va passer d’un tableau de taille 5000 à un
tableau de taille 10000. Ce qui peut être une grosse perte de mémoire.
D’un autre côté supprimer et refaire un tableau à chaque fois que le tableau est plein
est coûteux en écriture.
5.4. LinkedList :
Implémentation de l’interface List. La LinkedList est un Objet. Contrairement à
l’arrayList, il n’y pas de tableau derrière une LinkedList.
Ici, on aura une tête (head) qui est le premier élément de la liste. On connaîtra les autres
éléments de la liste grâce à cette tête. En effet, celle ci pointe vers l’adresse de la valeur
suivante de notre liste. Cela implique qu’on ne pourra pas directement chercher des éléments
avec leur indice.
Elles sont cependant plus lentes si vous devez ajouter ou supprimer des données au
milieu et au début (car beaucoup d’éléments à déplacer). Car il va falloir vérifier qu’ajouter
l’élément ne va pas dépasser la taille du tableau et ensuite il faut déplacer les éléments du
tableau à partir de l’indice souhaité pour pouvoir après insérer notre élément.
Avec une linked , il suffira de rajouter un noeud et de changer les références (même
si il va falloir parcourir toutes la liste pour tomber sur le bon élément ).
Pour résumer à l'extrême, si vous effectuez beaucoup de lectures sans vous soucier de
l'ordre des éléments, optez pour une ArrayList ; en revanche, si vous insérez beaucoup de
données au milieu de la liste, optez pour une Linkedlist
ArrayList LinkedList
ArrayList est le meilleure choix lorsqu’on LinkedList est le meilleur choix lorsqu’on
veut stocker et accéder à des données veut manipuler des données
6. Visibilité :
La visibilité s’applique à un membre(attribut ou méthode) d’une classe. Il en existe 4 types.
- Private -
- Public +
- Protected (fait référence à l’héritage) #
- Package (Sans mot-clé) ~
6.1. Private :
Quand l’attribut private est appliquée sur un champ, il n’est pas accessible en dehors de cette même
classe sauf via un accesseur (getter) ou un mutateur (setter) (puisqu’ils sont public).
Exemple :
Un attribut nombre déclaré comme ceci :
private int nombre;
6.2. Public :
La visibilité Public permet d'accéder aux champs à partir de toutes les autres classes, on peut y
accéder comme on le souhaite autant pour lire que pour modifier !
Exemple :
Un attribut nombre déclaré comme ceci dans la classe Projet :
public int nombre;
Je peux y accéder via :
[Link]([Link]);
6.3. Protected :
La visibilité protected est utilisée en héritage lorsqu'on veut que les attributs et les méthodes de la
classe mère soit visibles dans la classe fille. Du coup, au lieu de mettre le membre comme étant
private dans la classe mère, on le met protected.
Nous l’avons utilisé dans notre projet pour la classe Chest qui héritait de la classe Bag.
Exemple :
public class Employe {
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 y accéder sans restriction via l'héritage, ce qui n'aurait pas été possible si
l'attribut était private.
6.4. Package :
Pour la visibilité Package il n’y a pas de mot-clé. Elle permet de rendre les membres accessible par
l’entièreté du même package.
Exemple :
Créons une classe Esi.
public class Esi {
boolean isReussi;
Toutes les classes qui se trouvent dans le même package auront accès aux attributs et aux méthodes de
la classe Esi.
6.5. Intérêt ?
L’intérêt de mettre des visibilités est de gérer la portée qu’aura notre champ et ainsi de pouvoir le
contrôler et empêcher que des actions non shouhaitées soient effectuées sur nos champs ( →
mécanisme d’encapsulation).
Exemple :
Nous avons un attribut publique qui indique le nombre de vies restantes du joueur. N’importe qui
pourrait, dans ce cas, modifier son nombre de vie restante comme bon lui semble. Alors qu’en private
c’est impossible.
La différence est qu’avec un attribut public, il est directement modifiable en le citant alors qu’avec un
attribut private, il est modifiable avec un setter on peut donc y ajouter un traitement c-a-d comme une
condition par exemple.
Exemple :
public void setNbJambes(int nbJambes) {
if(nbJambes < 2) {
throw new IllegalArgumentException("AH !");
}
this.nbJambes = nbJambes
}
7. Encapsulation:
7.1. Définition :
L'encapsulation est un concept consistant à rassembler des données et des méthodes dans une structure
en cachant l'implémentation de l'objet, c'est-à-dire en empêchant l'accès aux données par un autre
moyen que les méthodes proposées (getter, setter ou méthode définie par le programmeur ). Pour
empêcher l’accès des attributs on utilisera des visibilités différentes : public, private, protected,
package (cf: Visibilité)
7.2. Exemple :
public static void main ( String args []){
Personne pers = new Personne;
[Link]("Gaïa"); // <- encapsulation
[Link]("nom : " + [Link]() ) ;
// affichera le nom :Gaïa
}
public class Personne{
private String nom;
Personne(){ }; // constructeur vide
// méthodes proposées pour accéder à la donnée :
public String getNom(){
return nom;
}
public void setNom(String name){
this.nom = name;
}
}
7.3. Explication:
L’encapsulation permet de dire que la variable i de la méthode A concerne uniquement cette méthode.
Pareil pour la méthode B. Les deux i ne sont pas les mêmes!
Donc l’encapsulation permet d’encapsuler des choses qui ne seront donc pas modifié par un autre
endroit du code.
L’assignation est une expression (qui comprend une opération, ex : + - * / …).//encore définir
expression
En java, on l’utilise avec un opérateur d’assignation pour attribuer une valeur à une variable. Elle a un
type (celui de la variable) et une valeur (celle du left hand side) . On considère la variable de gauche
comme étant le premier nombre de l'opération mais aussi la variable dans laquelle il faudra mettre le
résultat.
int a = 1;
int b = 2;
int c = 3;
a = b = c;
La grammaire nous apprend que l’assignation s’opère de droite à gauche. On pourra dès lors lire
l’instruction de cette manière
a = (b = c)
La valeur de c (=3) est assigné à b (b vaut maintenant 3) et b est assigné à a, donc a vaut maintenant
3.
DONC le résultat du premier opérande de l’assignement doit-être une variable, sinon cela ne
compilera pas.
exemple:
a = 2 = c; // ne compile pas
Autre cas;
int a,b,c,d,e;
a = b = c = d = e;
que vaut a?
Cette instruction ne compilera pas! Pourquoi? Parce que la variable e n’a pas été initialisé (aucune
valeur n’est assigné à e). La variable e est la seule minimum nécessaire afin que le code compile.
Autre cas;
int a,b,c,d;
boolean e = 2 == 2; //je sais c’est tordu, mais ça montre qu’on a compris les concepts
a = b = c = d = e;
que vaut a?
Autre cas;
par contre
a = b = c = d; //compile
4e DONC une constante ne peut pas se mettre dans le premier (elle ne peut se mettre que dans le
dernier, le principe est que sa valeur ne change pas) opérande de l’assignation.
Autre cas;
Comme il est possible de faire en une ligne plusieurs déclaration(séparée par une virgule):
int a,b,c;
il est aussi possible de faire plusieur assignation en une ligne:
int a, b, c = 2;
a, b et c ont 2 comme valeur.
++i :
i = i + 1; // i est incrémentée
++i = i; // l'expression (++i prend la valeur de i)
// pré-incrémentation => l'incrémentation se fait PRÉcédemment à
l'assignation de l'expression
I est incrémenté puis donne sa valeur à l’expression, alors que dans le cas de la
i++:
[Link](i++); //affiche 1
[Link](i); //affiche 2
}
//réponse
1
2
[Link](++i); //affiche 2
[Link](i); //affiche 2
[Link](i); //affiche 1
i = 1;
i = ++i;
[Link](i); //affiche 2
}
//réponse
1
2
Une fois l’espace alloué en mémoire pour n composantes de type T, on ne peut pas la changer la taille
du tableau. Le tableau est de type référence.
10.1. Déclaration:
TypeName [] Name
Après la déclaration, la variable tab existe , mais n’est pas encore initialisée à un tableau.
→ tab ne référence pas encore, elle contient la valeur null.
10.2. Création :
Deux manières de créer un tableau :
1) En l’initialisant manuellement
Exemple :
int[] tab = new {int, int, int} ou encore int tab[] = new {int, int, int}
Les deux manières sont correctes mais nous n’utilisons plus la syntaxe “int tab[]” car avec celle-ci
nous lisons directement que c’est un tableau d’entier.
Le token 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.
Exemple :
Lors de la création les valeurs par défauts sont : Numérique : 0 Booléen : false Référence : null
Char : ’\0’
Les tableaux sont des objets donc il est possible d’utiliser leur attributs et leurs méthodes:
Exemple : [Link] = la taille du tableau
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 [ ].
La classe utilitaire/statique [Link] n’est valable que pour les tableaux à une dimension :
● binarySearch( int [] a , int key) : a → Liste key → ce que tu cherches dans la liste
● copyOf, copyOfRange() : copie tout ou partie de tab
● fill() : remplit le tab
● hashCode() : calcul le hash
● sort() : trie le tab
● setAll(tab, opération) opération pour chaque valeur. Depuis jdk8 l'operation peut etre une
operation lambda.
● parrallelPrefix() : opération par paire.
● deep toString : représentation en profondeur
● equals : égalité des valeurs de deux tableaux
● deepEquals : égalité “ profonde”
● static <T> List <T> asList(T...a) : retourne une liste fixe (de taille fixe) à partir de l’array mis
en paramètre ou des valeurs mises en paramètre (voir var args)
● static boolean[] copyOf(boolean[] original, int newLength) : renvoie une copie du tableau
avec la taille spécifé. Si on à a = {vrai, faux}, et que la taille est 4 on va retourner {vrai,
faux,faux,faux} car on rajoute des éléments si il faut
On ne peut appliquer des opérations arithmétiques sur les tableaux, il est impossible
d’additionner deux tableaux par exemple.
Différents cas :
int [][] test = new int [2]; // Ne fonctionne pas car tu déclares un tableau multidimensionnel et
tu ne donne la taille que d'une dimension.
int [][] test = new int [2][3]; Création avec 2 lignes et 3 colonnes
int [][] entiers = new int [] {1,2}; // Ne correspond pas à la grammaire java, il faut faire : int[][]
entiers = {{1}{2}};
int [][] entiers = new int [] {{1},{2}};// Aurait pu fonctionner si on avait déjà déclaré un tableau
avant
int [][] entiers = {{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 pas car on ne donne pas la taille et les
valeurs en même temps. c'est l'un ou l'autre.
12. [Link]/out/err :
System est une classe (package [Link], inclut par défaut dans chaque fichier) regroupant trois
attributs assez connus tels que in, out et err. Ceux-ci permettent à notre programme de pouvoir
communiquer avec l’utilisateur/développeur via la console.
12.1. L’attribut in
L’attribut “in” s’occupe du flux d’entrée et fait référence à la classe InputStream. Typiquement ce
flux correspond à l’entrée au clavier ou à une autre source d’entrée qui doit être spécifiée.
Exemples :
//Exemple pour out
//Exemple pour in
try{
int a; // valeur décimale du premier caractère lu
a = [Link](); // lit le premier byte = caractère ASCII
[Link]("Valeur: " + a); // affiche la valeur ASCII du
premier caractère
}catch(IOException e ){ //exception lancée si le premier byte ne peut
pas être lu pour une quelconque raison
[Link]([Link]());
}
/* Exemple pour err
L'attribut err reprend les mêmes méthodes que out vu qu'ils font
référence à la même classe (PrintStream).
*/
try{
throw new IllegalArgumentException("test");
}catch(IllegalArgumentException e){
[Link]([Link]()); //affiche l'exception via le flux
de sortie erreur (convention).
}
où 3 correspond au déplacement
13.1. La base:
Les mots clé (token) 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
survient, il y'a dans le catch {} les instructions qui vont 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 inversement.
Exemple :
int a = 100 ;
try {
int b = [Link]() ;
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) {
[Link](« Division par 0 impossible ») ;
}
13.3. Méthode:
Étant 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(), méthode printStackTrace ()
(montre le chemin que le programme à fait avant de tomber sur une erreur) on utilise :
[Link]() ;
13.5. Finally :
Le mot clé́ (token) finally consiste à̀ exécuter une partie de code quoi qu'il arrive,
même si l'exception survient 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 ressources allaient se fermer
normalement. Maintenant il existe une alternative pour pouvoir fermer ces ressources quoi
qu'il arrive. On l'appelle try-with-ressources.
If your code has a return statement inside the try or catch block, the code inside the
finally-block will get executed before returning from the method.
You don't need both a catch and a finally block. You can have one of them or both of them
with a try-block, but not none of them. Due to the finally block the code still closes the filer
reader even if an exception is thrown.
Important: The finally block is a key tool for preventing resource leaks. When closing a file
or otherwise recovering resources, place the code in a finally block to ensure that resource is
always recovered.
Exemple:
If an exception is thrown inside a finally block, and it is not caught, then that finally block is
interrupted just like the try-block and catch-block is. That is why the example had the
[Link]() method call in the finally block wrapped in a try-catch block:
That way the [Link]("--- File End ---"); method call will always be executed. If
no unchecked exceptions are thrown that is. More about checked and unchecked in a later
chapter.
You don't need both a catch and a finally block. You can have one of them or both of them
with a try-block, but not none of them. Due to the finally block the code still closes the filer
reader even if an exception is thrown.
Les ressources qui seront fermées se trouveront dans une parenthèse qui suit le try. On peut
toujours utiliser des clause finally mais la fermeture des ressources se fera avant l'exécution
de ces clauses. A noter qu'il est obligatoire de définir les ressources à fermer dans les
parenthèses qui suivent le try, sinon, erreur de compilation.
Exemple :
String path = "monfichier";
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return [Link]();
} catch (NoSuchFileException e){
// traitement de l ' absence du fichier
}
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 à la fin des instructions, qu'elles se soient bien
passé (fin du try, pas besoin d'aller dans le catch) ou mal passée(passage par le catch).
The following example reads the first line from a file. It uses an instance of BufferedReader
to read data from the file. BufferedReader is a resource that must be closed after the program
is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return [Link]();
}
}
14.1. La base:
Le foreach permet de parcourir toutes les valeurs d'un objet itérable.
14.2. Grammaire :
EnhancedForStatement:
for(Type Identifier : Expression) Statement
Type :
Doit être du même type que ce qui compose l'élément à parcourir sinon erreur de compilation.
(à noter que si un objet hérite d’une classe , il appartient aussi à cette classe)
(Donc pour un tableau 2D, vu qu'il est composé de tableau d'élément, il faudra qu'il soit un
tableau d'éléments, ensuite, on refera un foreach pour parcourir le tableau a une dimension).
Identifier :
Le nom de la variable du type précédemment écrit.
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. → OK pour consulter mais pas
pour modifier.
L'ordre dans lequel on va parcourir les éléments est l'ordre de l'élément en partant du début.
Exemple:
for (String mot : dictionnaire ){ //La variable mot prendra une valeur
qui est contenue dans le dictionnaire à chaque itération et cela jusqua
ce que tout le dictionnaire ai été parcourue.
[Link](mot);
}
public void a
fficher ( Set<Integer> set ) {
for( Integer val : set ) {
[Link]( val );
}
}
For each:
● does not allow to modify the list
■ trying to do so will most likely result in ConcurrentModificationException
● you don't know the index of the element
■ you cannot refer to previous/next element
● efficient in all cases because uses Iterator specific for the collection
■ efficient in case of LinkedList
● works not only with every Collection, but with every Iterable
■ you can easily replace with your own class, it just has to implement Iterable
● more robust (less code, fewer special characters)
For:
● allows to modify the list, e.g.:
○ you can add extra element at the end of list and it will be also iterated
through
● you know the index
○ can be used to refer to another list of the same size
○ can be used to refer to previous/next element
15. If:
15.1. Grammaire :
IfThenStatement :
if ( Expression ) Statement
IfThenElseStatement :
if ( Expression ) StatementNoShortIf else Statement
IfThenElseStatementNoShortIf :
if ( Expression ) StatementNoShortIf else StatementNoShortIf
Il est exécuté après avoir testé l'expression, si elle est vraie alors on exécute le bloc
d'instructions qui suis le if, si cette expression est fausse, on exécute l'instruction qui suis le
else.
Quand on exécute 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 but si par exemple, on les utilise afin
de rassembler un bloc d'instruction.
Les accolades {} permettent de délimiter un bloc, une ligne de code simple terminée par un ';'
(instruction) est un bloc. Si tu veux que dans ton bloc il y ait plusieurs instructions, il te faut
les accolades.
En fait, les accolades sont présentes dans la structure « normale » des conditions, mais
lorsque le code à l'intérieur de l'une d'entre elles n'est composé que d'une seule ligne, les
accolades deviennent facultatives.
Exemple:
if ([Link]())
[Link]();
[Link]("Hello"); //n'exécute que la première condition.
else
[Link]();
if (ttc < 1000.) { //ici, on a plusieurs instructions donc il faut mettre des
accolades.
tauxr = 0;
tauxr2 = 1;
} else {
tauxr3= 0;
tauxr4 = 1;
}
In the example above, the else is indented with the inner if statement. It prints "bbb" only if
num > 0 and num >= 10, which means it prints only if num is 10 or greater.
In the example below, the else is indented with the outer if statement.
if ( num > 0 )
if ( num < 10 )
[Link]( "aaa" ) ;
else
[Link]( "bbb" ) ;
This prints if num <= 0. Depending on which if the else is paired with, you can get different
results.
By now, you should know that Java doesn't pay attention to indentation. So both examples
above are the same to Java, which means that it must pick one version over the other.
Which one does it pick? It picks the first one. This phenomenon of having to pick between
one of two possible if is called the dangling else.
An else matches with the nearest, previous, unmatched if that's not in a block.
By not in a block, I mean that the else is outside the block that the if is inside.
Thus,
if ( num > 0 )
if ( num < 10 ) // Previous unmatched if
[Link]( "aaa" ) ;
else // Matches with previous unmatched if
[Link]( "bbb" ) ;
The else matches with the previous, unmatched if not in a block. This happens to be the outer
if. There is an unmatched if that's the inner if, but that's in a block, so you can't match to it.
Notice the else sits outside of the block. An else can not match to a previous if if the else is
outside a block, while the previous if is inside.
Exemple:
if ([Link]())
if ( resident . isVisible ())
resident .greet("Hello");
else
[Link]();
//a quelle condition appartient le else? Comment résoudre le problème?
Solution:
if(x>0){
if(x < 10)
print(A)
else
print(B)
}
An else keyword always associates with the nearest preceeding if keyword that does
NOT cause a syntax error
Il est important de savoir que le if-else simple avec une instruction peut être remplacé par un
operateur ternaire “?”.
Exemple :
String salutation = (heure > 12) ? « Bonjour » : « Bonsoir»
Le premier choix sera effectué si la condition est vraie, sinon il ne sera pas effectué́.
Il existe une expression conditionnelle exprimée avec l'opérateur ternaire, (qui possède trois
opérandes) nous permettant d'obtenir la même structure et le même résultat. Voici une
deuxième version de la fonction max() en utilisant cet opérateur ternaire.
(a > b) ? a : b; is an expression which returns one of two values, a or b. The condition, (a > b),
is tested. If it is true the first value, a, is returned. If it is false, the second value, b, is returned.
Whichever value is returned is dependent on the conditional test, a > b. The condition can be
any expression which returns a boolean value.
Exemples:
if (i == 2) {
i = 6;
if (!n) {}
if (i == 3) {
i = 4 ;
} else {
i = 5 ;
}
if (i==1)
i = 2;
else
i = 3;
16.1. La base:
Il est possible de définir une méthode dont le nombre d’arguments est variable. Varargs
donne une flexibilité sur la façon dont on utilise une méthode.
16.2. Notation:
La notation « … » utilisée dans un tel contexte est appelée « ellipse ». L’ellipse concerne des
arguments d’un type quelconque, primitif ou objet et peut être accompagnée d’arguments
classiques.
Exemples:
Exemples:
Valides:
public void parkPlanes (Plane... p) {...}
Invalides:
public void parkPlanes (Plane p...) {...} //bad syntax
Utilisation:
nt s
public i um1(int[] numbers){...} //calcule une somme
public i nt s um2(int... numbers){...} //calcule une somme
Les … représentent l’ellipse. Le type suivit de l’ellipse indique que la méthode peut accepter
un nombre variable d’arguments.
Quelle est la différence? L’appel de méthode.
Nous avons le tableau d’entier suivant: int [ ] Array = {2,3,4}; sum1 et sum2 sont capables de
faire la somme des éléments du tableau: sum1(Array), sum2(Array).
On pourrait aussi passer les éléments du tableau dans les params de la méthode sum2.
On ne sait pas le faire avec la méthode sum1.
17.1. Principe:
La nécessité de pouvoir écrire un compilateur, la nécessité de pouvoir décrire le langage
imposent que les règles soient clairement décrites. C’est le rôle de la grammaire.
17.2. Compilation :
17.3. Fonctionnement :
Une grammaire est une description finie de l’infinité des programmes
Un mot (token) doit être légal, grammaire lexicale
Une séquence de mots doit être légale, grammaire syntaxique
Le tout doit avoir un sens, sémantique
Nombre :
Chiffre
Chiffre Nombre
Chiffre:
one of 0 1 2 3 4 5 6 7 8 9
Ici, Nombre est le symbole de départ, Chiffre et Nombre sont des symboles terminaux.
Chiffre est défini comme étant soit 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
La règle de production de Nombre est la suivante : Un nombre est un Chiffre (première ligne)
OU un Chiffre suivi d’un Nombre (deuxième ligne).
La deuxième ligne stipule en fait qu’un Nombre est un Chiffre suivi d’un Nombre et comme
Nombre est un Chiffre ou un Chiffre suivi d’un nombre, tout nombre peut être écrit grâce à
cette grammaire.
1234 est le Chiffre 1 suivi du Nombre 234. 234 est le Chiffre 2 suivi du Nombre 23. 23 est le
Chiffre 2 suivi du Nombre 1. 1 est le chiffre 1. Par conséquent, il est possible d’écrire le
nombre 1234 (ainsi que tout autre nombres) avec la grammaire de Nombre.
Palindrome :
0
1
0 Palindrome 0
1 Palindrome 1
Explication :
17.4. Lexicale:
- Les symboles terminaux sont les caractères (characters of Unicode characters set).
- Les règles de production forment les mots (tokens), éléments d’entrée (input
elements) de la grammaire syntaxique.
UnicodeInputCharacter :
RawInputCharacter
UnicodeEscape
RawInputCharacter :
any Unicode character
UnicodeEscape :
\UnicodeMarker HexDigit HexDigit HexDigit HexDigit
UnicodeMarker :
u
UnicodeMarker u
InputElement:
Comment
WhiteSpace
Token
13.4. Syntaxique:
Il existe la classe Comparable qui est une Interface ne possédant qu’une méthode et qui
définit un “ordre naturel”. (Seul méthode : compareTo)
int compareTo(Object o)
@Override
public int compareTo(Explorer e) {
if (this.[Link]() > [Link]().getValue()) {
return 1; // si l'instance qui appelle la méthode est
supérieure à l'objet e
} else if (this.[Link]() < [Link]().getValue()) {
return -1; // si l'instance qui appelle la méthode est
inférieure à l'objet e
} else {
Une fois le compareTo créé, on peut utiliser les méthodes de collections pour trouver le max ,
le min ou même trier une collection.
import [Link];
public class Game implements Model {
@Override
public List<Explorer> getWinners() {
return [Link](EXPLORERS);
}
}
Pour trier une Collection, on va utiliser la méthode sort de la classe static Collections ou celle
de Arrays.
static <T extends Comparable<? super T>> void sort(List<T> list)
L’entête de cette méthode indique qu’elle a besoin d’une List Comparable. (ne suis pas sûr
mais autant dire ça à Codutti s’il demande)
Cette méthode va trier la liste passée en paramètre, (du plus petit au plus grand) selon
l’ordre définir par le compareTo. (avec une liste d'Explorateur, on aura l'explorateur avec la
plus petite fortune en premier et celui avec la plus grosse en dernier)
Integer retourne la valeur 0 si param1 == param2; une valeur inférieure à 0 si param1 <
param2 et une valeur > 0 si param1 > param2
Exemple :
Si une classe n’est utilisée qu’une seule fois on peut utiliser une classe anonyme. C’est une
classe locale qui n’a pas de nom et qui est à usage unique. (comme en JavaScript)
Explication :
[Link] permet de trier le premier paramètre (tab dans ce cas) de la manière du second
paramètre en créant un comparator d’objet Vidéo qui contiendra les 2 objets Vidéo à
comparer.
Le return va appeler la méthode compare de la classe Integer (class Integer car on ne peut
pas comparer des int, nous les transformons donc en Integer). Cela va donc comparer le
nombre de Likes de l’objet 1 par rapport à l’objet 2 et il va retourner :
- la valeur 0 si param1 == param2
- une valeur inférieure à 0 si param1 < param2
- une valeur supérieur à 0 si param1 > param2
19. toString:
En Java, la méthode toString() retourne une représentation d’objet sous forme de chaîne de
caractères.
Elle est définie dans la classe [Link] mais elle peut être Overridé dans une classe
enfant.
Exemple :
public Etudiant (int unNumero, String unNom, int annéeEtude) {
numero = unNumero;
nom = unNom;
annéeEtude = 1;
}
@Override
public String toString() {
return "nom + "," + numero + "," + annéeEtude";
}
Affichera :
Captain America, 45022, 1
Captain America, 45022, 2
Lorsque le [Link](corentin); est fait, il va rechercher la méthode toString() qui a été créée
dans la classe Etudiant car “captain” est un objet Etudiant.
@Override
public String toString() {
return this.heure + ":" + this.minute + ":" + this.seconde;
}
public static void main(String[] args) {
Moment moment1 = new Moment(3, 55, 12);
[Link](moment1);
}
Affichera : 3:55:12
Sans toString()
public static void main(String[] args) {
Moment moment1 = new Moment(3, 55, 12);
[Link](moment1);
}
Avec [Link]()
Exemple :
PrintWriter out = new PrintWriter(
new FileOutputStream("[Link]"));
[Link](10);
[Link]( "Hello" );
[Link] ();
21.1. This:
This sert à référencer l’instance de l’objet en cours d’utilisation( à soi même) .Elle apparaît
dans différents contextes : constructeur, attribut et méthode
21.2. Super:
22.1. Throw
Permet de déclencher une exception.
Exemple :
if([Link]()) {
throw new SandException("...fuck...");
}
Dans cette exemple, quand [Link] sera true, une erreur va être envoyée et “...fuck…”
sera affiché à l’écran.
22.2. Throws
Permet à une méthode de lancer une exception contrôlée. Le throws doit apparaître dans l’entête de la
méthode.
public void methode() throws OupsException {}
Quand on appelle une méthode qui peut lancer une exception contrôlée, on doit soit la gérer
par un “try-catch” soit déclarer qu’on la lance par un “throws” (on laisse passer l’exception).
do {
if(a==3) {
throw new IllegalArgumentException("message");
} else {
[Link]("Valeur de a = " + a);
}
} while(a++ < b);
}
Il va donc afficher :
Valeur de a = 1
22.3. RuntimeException
Les RuntimeException sont un cas particuliers parmis les exceptions, puisqu'elles n'ont
pas besoins d'être déclaré ni traité.
En effet, il s'agit d'exception relative aux erreurs de programmation, et qui ne devrait
normalement pas arriver... Si on devait toutes les traiter on se retrouvera avec des try/catch
partout ce qui rendrait le tout complètement illisible.
Donc pour les RuntimeException le throws est inutile... mais il est bien de le préciser car
cela indique aux développeurs qui utilisent la méthode qu'elle peut renvoyer une telle
exception. Il est bien également de le préciser dans l'entête de la javadoc
/**
* ...
* @throws ArithmeticException si j == 0
*/
public static double m(int i, int j) throws ArithmeticException {
return i/j;
}
Toutes les exceptions héritent de la classe Throwable, c’est la classe qui permet la gestion
des erreurs.
22.4. En résumé
Throws permet de prévenir le compilateur qu’une erreur pourrait être levée dans la méthode
en question.
Throw par contre va permettre de lever et de gérer une exception “manuellement”.
Exemple :
Une classe A (la voiture) fait appelle à la classe B (le moteur) qui contient une erreur.
La classe B :
public class Moteur {
public void avancer(){
//augmente la vitesse
if(vitesse > 130) {
throw new codeRouteException("Tu vas trop vite connard
!");
}
}
}
La classe A va donc être “préparée” à recevoir cette erreur va donc la gérer.
La classe A :
public class V
oiture {
public static void main(String [] args) {
try {
[Link]();
} catch(codeRouteException e) {
[Link]();
}
}
}
Exemple:
Chaque caractère permettant de réaliser notre regex tels que ^,$,*,+,{},[], … sont appelés
métadonnées.
L'intervalle [a-z0-9._-]+ représente dans un premier cas a-z toutes les lettres de l'alphabet
minuscules (il ne contient pas les caractères accentués) ensuite 0-9 représente donc les
chiffres de 0 à 9 et pour finir nous autorisons que notre chaîne se compose de . _ et -
Le + se trouvant à la fin de l'intervalle signifie que ce qu'il le précède (donc l'intervalle) peut
être répété 1 ou plusieurs fois.
Après le @ nous avons donc le même intervalle que celui qui précède le @ à l'exception du
+ qui devient {2,} cela signifie "au moins 2 fois ou plus".
Nous avons ensuite \\. qui permet de définir le point pour domaine ([Link]), on y
ajoute devant 2 anti-slash car le caractère . dans un regex correspond à "tout caractère".
(Par exemple, le regex "[Link]" on pourrait mettre n'importe quel caractère à la place du point).
Un anti-slash suffirait pour spécifier qu'on veuille le symbole point mais le deuxième
anti-slash permet déspécialiser le premier car un \ est également un caractère ayant une
signification dans un regex.
Et pour finir nous nous occupons du nom de domaine, il peut donc contenir les minuscules
a-z mais seulement de 2 à 8 caractères car le minimum de caractères que peut contenir un
nom de domaine est 2 et son maximum donc 8. (exemple: [Link] [Link])
import [Link];
ps : Un itérateur est un objet permettant de parcourir différent élément d’une collection et est
muni des méthodes hasNext(), next(),previous(). Il est utilisé implicitement par le foreach
→ Utiliser avant .
24.1. Le Stream:
Depuis Java 8 , on nous propose l’API Stream pour simplifier des traitements sur des
collections ou des tableaux ! ( Stream est un objet ! )
Le stream ne stocke pas de données. Il ne fait que transférer d’une source vers une
suite d’opérations
Un stream peut ne pas être borné (il a pas de limite , il est infini). ( mais Il faudra
cependant veiller à ce que nos opérations se terminent en un temps fini )
Un stream ne modifie pas les données de la [Link] il doit modifier les données
pour les réutiliser, il va construire un nouveau stream à partir du stream initial. ( Important
pour la cohérence du parallélisme !!)
Le chargement des données pour des opérations sur un stream s’effectue de façon
lazy. Cela permet d’optimiser les performances de nos applications. Par exemple, si l’on
recherche dans un stream de chaînes de caractères une chaîne correspondant à un certain
pattern, cela nous permettra de ne charger que les éléments nécessaires pour trouver une
chaîne qui conviendrait, et le reste des données n’aura alors pas à être chargé.
Les données passant par le stream peuvent être parcouru de 2 manières différentes.
Séquentiellement : un à un
Parallèlement : plusieurs à la fois
En fonctionnel il existe 2 type de méthode : intermédiaire et terminal (voir 24.2 et 24.3)
On peut appliquer à un stream plusieurs méthodes intermédiaires mais une seul terminale
sorted(trie le stream)
Exemple :
on pourrait utiliser un for each, mais les expressions fonctionnelles nous permettent déjà de
faire un .forEach.
cependant, on aura préférence à utiliser un stream pour que ça soit plus performant:
la valeur 8 est stockés dans les attributs de l'instance n2 de type Integer. L'objet est stocké
sur le tas et une référence pointant vers cet objet est stockée dans la pile.
Attention , il faut savoir que Byte, Short, Integer, Long,Float et Double (tous les Wrappers qui
représentent des nombre) font partis de la classe Number qui fait partie de la classe Object
[Link]. Integer :
[Link].1. Champs :
MAX_VALUE : valeur maximale d’un Integer 2^31 (exposant)
MIN_VALUE : valeur minimale d’un Integer, -2^31
SIZE : le nombre de bits utiliser pour représenter un int en complément A2
TYPE : le type que représente Integer (c-a-d int)
[Link].2. Méthodes :
static int parseInt(String s) : converti un string en int decimal. (pas sûr)
static Integer valueOf (String s) : return an Integer object holding the value of the specified String.
static String toBinaryString(int i) Returns a string representation of the integer argument as an
unsigned integer in base 2.
double doubleValue() : retourne la valeur de l’Integer en double.
int intValue() : retourne la valeur de l’Integer en int.
[Link]. Double :
[Link].1. Champs :
(je comprends pas les tailles help)
static int SIZE : nombre de bits pour représenter un double
static Class<Double> TYPE : l’instance représentant le type primitif de double (no idea what
it means)
[Link].2. Methodes :
boolean isInfinite() : dis si le Double est infini en magnitude (?)
booblean isNaN() : dis si le Double n’est pas un nombre.
static boolean isNan (double v) : dis si le double en paramètre n’est pas un nombre
[Link]. Float :
(plus tard besoin de repos)
[Link].2. Methodes :
[Link]. Boolean :
[Link].1. Champs :
static Boolean FALSE : the Boolean object corresponding to the primitive value false.
static Boolean TRUE : the Boolean object corresponding to the primitive value true.
static Class<Boolean> TYPE : the Class object representing the primitive type boolean
[Link].2. Methodes :
boolean booleanValue() : retourne la valeur booléenne de l’objet
static Boolean valueOf (boolean b) : retourne un Booléen représentant la valeur booléenne
mis en paramètre
[Link]. Character :
[Link].1. Champs :
static int SIZE : the number of bits used to represent a char value in unsigned binary form,
16
static Class<Character> Type : The Class instance representing the primitive type char
[Link].2. Methodes :
char charValue() : retourne la valeur de l’objet Character courant.
static boolean isAlphabetic (int codePoint) : détermine si codePoint fait parti de l’alphabet.
[Link]. Number :
25.3. Boxing/Unboxing :
Exemple :
La valeur 8 est stockés dans les attributs de l'instance n2 de type Integer. L'objet est stocké
sur le tas et une référence pointant vers cet objet est stockée dans la pile.
Normalement on aurait dû écrire (car Integer est un objet):
L’unboxing est le phénomène inverse. C’est quand on va sortir le type primitif de son wrapper.
exemple :
List <Integer> list = new ArrayList<>();
int blackWidow\<3 = 5;
[Link](blackWidow\<3); // pour ajouter blackWidow<3 qui est un int dans list, le compilateur va
envelopper blackWidow<3 dans un Integer. C'est le phénomène de boxing
int loki = [Link](0) // loki est un entier mais va recevoir un Integer. Le compilateur s'occupe donc
d'unboxer l'élément de la liste d'Integer pour pouvoir donner sa valeur à loki.
26.1. Label:
Toute instruction peut recevoir une étiquette (label)
LabeledStatement :
Identifier : Statement
26.2. Break:
BreakStatement :
break Identifier(opt);
· Permet d’arrêter brutalement une instruction :
Si étiquette →arrête l’instruction étiquetée
Si pas d’étiquette →arrête l’instruction englobante
· Il est associé à une structure conditionnelle (boucle for, while), sans laquelle la boucle ne
ferait jamais plus d'un tour.
· 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 boucles imbriquées.
Exemple:
int nb;
entrée : while(true) {
nb = clavier . nextInt ();
if (nb > 0) {
break entrée; // break la boucle entrée quand le nombre entré est
supérieur à 0.
}
[Link]("Veuillez donner un nb positif");
}
int i =1 ;
lab1 : if (i==1) {
break lab1 ;
[Link] (2); //ne va pas être affiché car le break à briser le
bloc d'instruction lab1
}
[Link] (3); // affiche : 3
int nb;
while(true) {
nb = clavier . nextInt ();
if (nb>0) break; /
/ on casse le while si nb >0
[Link]( "Mauvais nb. Recommencer."); // ne va pas
être afficher si le nombre est >0
}
26.3. Continue:
ContinueStatement :
continue Identifier(opt) ;
Exemple:
int x = 1;
for(int x = 0; x <= 10 ; x++){
if(x == 7){
[Link]("Division par zéro!");
continue; // on va réitérer la boucle et donc incrémenter la valeur de x
}
double a =1.0/(x-7); //1 ne sera jamais divisé par 0
[Link](a);
}
starting loop:
in loop: 0
survived first guard
survived second guard
in loop: 1
survived first guard
survived second guard
in loop: 2
in loop: 3
survived first guard
survived second guard
in loop: 4
survived first guard
end of loop or exit via break
You can label a block, not only a for-loop, and then break/continue from a nested block to an outer
one. In few cases this might be useful, but in general you'll try to avoid such code, except the logic of
the program is much better to understand than in the following example:
try{
OutputStream out = new FileOutputStream(file);
[Link](10); //On ne pourra écrire que des bytes.
[Link](); //libère les ressources quand on a fini d'écrire.
try{
DataOutputStream out = new DataOutputStream(new
FileOutputStream(file));
[Link](true); //permet d'écrire des données primitives.
[Link]();
FileReader ( pour lire un fichier texte ) : int read() → lit un caractère (-1 si fin du
fichier)
FileWriter ( pour écrire un fichier texte) : void write(int c ) → écrire le caractère stocké
dans c
BufferedReader (lire ligne par ligne ( et pas seulement byte par byte ) →
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(fichier)));
String ligne1 = [Link]();
// readLine() retourne null quand on est à la fin du fichier.
[Link]();
[Link]("ligne 1 : " + ligne1);
Les méthodes d’une classe abstraites sont justement abstraites. C’est à dire qu’il ne faut spécifier, à
l’intérieur de la classe, que l’en-tête de la méthode.
Exemple :
abstract void crier(); // pas de visibilité, ajout du mot clé abstract et non définition du code de la
méthode
L’implémentation de la méthode se fera dans la classe qui va héritée de notre classe abstraite.
public class Lion extends Felin {
void crier() {
[Link]("Je rugis dans la savane !"); //Ici on défini la méthode crier de Animal qui est
étendu par Félin
}
}
Une classe abstraite est comme une Interface sauf que toutes ses méthodes ne sont pas implicitement
abstraites. Il faudra alors spécifier le mot clé abstract quand on voudra créer une méthodes abstraites.
Une classe abstraite peut, contrairement à une interface, posséder des méthodes non abstraites et donc
directement implémentées dans la classe.
Elle peut aussi posséder des attributs autres que static et final.
Attention. Comme les classes abstraites se transmettent par héritage et non par implémentation, il
n’est pas possible pour une classe enfant d’avoir deux parents abstraits. Car l’héritage multiple est
interdit en Java.
Exemple :
Partons du principe que tous les animaux mangent de la même façon , considérons donc
qu’ils soient vegan. Par contre, ils se déplacent tous différemment, les uns avec leurs pattes,
les autres avec leurs ailes.
Il sera alors plus judicieux d’utiliser une classe abstraite vu que l’implémentation de
manger() est commune à toute les classe. (La méthode se comporte de la même façon) Et
de mettre en abstract la méthode seDeplacer() (car celle ci voit son implémentation modifiée
en fonction de la classe qui l’invoque)
30. Polymorphisme :
Le polymorphisme :
poly, grec : plusieurs
morph, gerc : forme
Le polymorphisme est la capacité d’une méthode à avoir plusieurs formes. C’est à dire qu’elle peut
avoir plusieurs comportements. Exemple : [Link]() lance un Kamehameha et Vé[Link]()
lance un Final Flash. La méthode attaquer() est appelée de la même manière mais réagit différemment
en fonction de l’objet (et surtout de la classe qui l’invoque).
Classes abstraites/Interfaces:
Une méthode abstraite n’a pas de code. Il ne sera défini que quand on va implémenter l’interface ou
hériter de la classe.
L’annotation Override est optionnelle dans ce cas. (Vu qu’il n’y a rien à réécrire)
C'est un mot réservé du langage qui permet de définir des boucles. Il sert à coder le "pour".
Si on connaît le nombre de récurrence, on utilisera souvent un for classique. Sinon on se
contentera en général d'un while ( moins depuis java 8 vu qu’on peut mettre plusieurs
expressions dans un for) . Il existe deux variantes pour le for : le for classique et le foreach
Exemple d'utilisation :
Grammaire :
Le for est composé de trois parties (dans la parenthèse) qui sont toutes facultatives.
ForInit :
Il permet d'initialiser la boucle et elle est facultative (pas d'initialisation si elle est absente); Il
y a 2 possibilités de déclarations. Une déclaration de une ou plusieurs variables locales ou
une liste d'assignations. (int i=1,j=5,k=N).
On n’utilise pas le for init car on veut que la variable incrémentée par la boucle puisse être
utilisée dans un autre endroit que la boucle. Ici, on l’utilise dans le do while.
Expression :
L'expression doit être de type booléen qui permettra de mettre fin à la boucle et elle est
facultative (une boucle infinie aura lieu si l'expression est absente à moins d'avoir un break
ou return dans la boucle).
ForUpdate :
Cette partie a pour but de mettre à jour les indices avant de tester à nouveau la condition.
On peut y trouver une liste d’expressions instructions (comme le second cas de la partie
ForInit).Les mêmes exemples sont donc valides. (Si elle est omise, pas de mise à jour).
Statement :
Un exemple récapitulatif :
Compléments :
Il n’y a qu’une seule instruction dans la boucle. Mais si on examine ce qu’est une instruction
dans la grammaire, on trouve, dans la liste des possibilités, le block. Un block est une suite
d’instructions entre accolades qui a donc le statut d’instruction unique. Ce qui permet de le
Oui ==>
-------------------------------------------------------------------------------------------------------
For ( init,expr,update){
init statements;
while(expr){
}
statements;
update;
}
-------------------------------------------------------------------------------------------------------
while(expr){
for(expr){
statements;
statements;
}
}
32. Constructeur:
Un constructeur a pour but d’instancier un objet.
Instancier un objet correspond à le construire en mémoire :
Un constructeur se définit comme une méthode standard, mais ne renvoie aucune valeur.
Ainsi, le constructeur d'un objet porte le même nom que la classe et ne possède aucune
valeur de retour (même pas void).
- un constructeur porte le même nom que la classe dans laquelle il est défini.
- un constructeur n'a pas de type de retour (même pas void).
- un constructeur peut avoir des arguments.
class Toto{
private int age;
private char sexe;
private float taille;
Toto(int age, char sexe, float taille){
this.age = age;
this.sexe = sexe;
this.taille = taille;
}
}
Imaginons par exemple que pour l'exemple précédent on veuille pouvoir définir le sexe de
Toto grâce à un entier valant 0 ou 1, ainsi qu'avoir la possibilité de passer en paramètre la
lettre 'M' ou 'F', on peut alors définir deux constructeurs pour lesquels le type du second
argument sera différent. De plus, on va montrer de quelle manière il est possible de
contrôler le caractère entré en paramètre :
class Toto{
int age;
char sexe;
float taille;
Toto(int age, char sexe, float taille){
this.age = age;
if ((sexe=='M')||(sexe=='F')) {
this.sexe = sexe;
}
else {
[Link]("Erreur d'initialisation");
}
this.taille = taille;
}
} else {
this.maison = maison
this.année=année
this.moyenne=moyenne
}
32.1. Getter :
Le getter permet de retourner la valeur d’un attribut private
32.2. Setter :
Le setter permet de modifier la valeur d’un attribut static.
L’intérêt d’avoir un Setter est de pouvoir appliquer son action que d’une certaine façon,
définie par le programme. Si un setter est défini, on ne pourra pas modifier l’attribut
autrement que par son setter.
33. Object:
Un langage orienté objet permet de créer ses propres types, liés au problème à résoudre.
Il est apparu suite aux limites de la programmation procédurale (crise du logiciel) et permet
d’écrire des programmes plus lisibles, compactes et robustes.
Une classe d'objet ne comprend pas de méthodes static (voir mot static)
Exemple :
pour vérifier la validité des paramètres, il suffit d’ajouter des tests en début de constructeur ,
exemple :
if(unAuteur==null || [Link]()==0) {
throw new IllegalArgumentException("Auteur invalide : " +
unAuteur);
}
auteur = unAuteur;
titre = unTitre;
publiée = false;
nbLikes = 0;
}
Cela permet d'éviter de donner des valeurs invalide, pour palier à ce problème on utilise des
méthodes publiques.
l'accesseur d'un attribut (d'un objet), (par défaut get/is(booléen)Attribut ) donne la valeur de
ce dernier
Exemple : [Link]. println ([Link] ());
titre = unTitre;
}
Même si les attribut ne sont pas initialisé dans le constructeur il existe une valeur par défaut:
■ 0 pour les nombres ;
■ null pour les références ;
■ false pour les booléens.
Il existe même un constructeur par défaut, il est sans paramètre et ne fait rien. Il n'est plus
disponible si un autre constructeur est fourni.
Le constructeur, les méthode et les attribut d'un objet peuvent être représenté par "this" (voir
le mot this)
1
Problème: Question à résoudre par des méthodes logiques, rationnelles, dans le domaine
scientifique.(petit Larousse 1998).
² En , on appelle instance d'une classe, un objet avec un comportement et un état, tous deux définis
programmation orientée objets par la classe. Il s'agit donc d'un objet constituant un exemplaire de la
classe. Dans ce contexte, instance est un anglicisme, qui signifie « cas », « exemple ». (wikipédia)
³ L’état d'un objet est sa forme à un instant donné, telle que décrite par les valeurs de l'ensemble de ses
propriétés.(j'ai oublié la source, sorry )
4
Une méthode est un morceau de code réutilisable qui effectue une action bien définie. Elles se
définissent dans une classe. Il y a deux « familles » : les natives et les nôtres. Le principal avantage
des méthodes est de pouvoir factoriser le code : grâce à elles, vous n'avez qu'un seul endroit où
effectuer des modifications lorsqu'elles sont nécessaires. ( OpenClassRooms:
[Link]
5
Les types primitifs et référence :
Les types primitifs sont des types natifs de java , cela comprend byte, int, char, double, boolean.
Lors de la déclaration d'un type primitif (ex: int i) ,un espace mémoire est allouée directement variable
i. Lors de son assignation: la valeur de i vient se mettre à l'emplacement de la mémoire correspondant
à la variable. (ex: i = 1), Dans cet espace mémoire est écrit un encodage de l’entier « 1 ».
Type référence : Lors de la déclaration d'un type (ex : p = Pays) , il y a un espace mémoire permettant
de stocker une référence. Au moment de l'assignation (ex: p = new Pays()), un espace mémoire est
alloué permettant de stocker un objet de type de Pays et l'adresse de cet espace est ensuite référencé
par la variable p.
34. Objects :
Objects est une classe comprenant uniquement des méthodes utilitaires statiques qui
servent à la manipulation d’objets. (utilitaire signifie static).
34.1. deepEquals:
public static boolean deepEquals (Object a, Object b) : retourne vrai si les deux objets
sont profondément égaux.
Deux objets null sont profondément égaux. Si les deux arguments sont des Array, alors c’est
la méthode [Link]() qui va déterminer l’égalité profonde. Sinon l’égalité est
testée par l’equals du premier argument.
Deux Arrays sont profondément égaux s’ils références vers des tableaux de même taille et
dont les éléments aux même indices sont deepEquals. Le equals, lui va comparer
strictement les éléments d’un tableau (s’il tombe sur des références ,à l’intérieur, du tableau,
il va comparer les références et non les éléments pointés par les références).
Exemple :
public static void main(String[] args) {
34.2. compare:
public static <T> int compare(T a,T b, Comparator<? super T> c)
Retourne 0 si les 2 arguments sont identiques (donc aussi tout les deux null) et [Link]()
au sinon. On choisit avec le comparateur si un paramètre null renvoie une
nullPointerException.
Elle reçoit en paramètre les objets à comparer et le comparateur.
Différence avec compareTo → compareTo renvoie une erreur pour les objets null.
34.3. hash:
public static int hash(Object... values):
Génère un hash code pour les valeurs entrée en paramètre. Le code de hachage est généré
comme si toutes les valeurs d'entrée étaient placées dans un tableau, et que ce tableau était
haché en appelant [Link] (Object []).
Cette méthode est utile pour implémenter [Link] () sur des objets contenant
plusieurs champs. Par exemple, si un objet a trois champs, x, y et z, on pourrait écrire:
@Override
public int hashCode() {
return [Link](x, y, z);
}
⚠ Lorsqu'une seule référence d'objet est fournie, la valeur renvoyée n'est pas égale au
code de hachage de cette référence d'objet.
35. Switch:
35.1. La base:
Java offre la possibilité d’effectuer des actions quand certaines conditions sont remplies. Ce
sont des instructions et ces instructions sont :
si...alors
si...alors...sinon….
si... sinon si … alors... sinon...
selon que...
switch...case
Ici nous allons voir comment utiliser l’instruction switch. Une instruction switch vérifie si
une variable est égale à une liste de variables. La variable dans le switch peut être un byte,
short , int ou char. Cependant depuis Java 7, le switch supporte aussi le String.
{{SwitchBlockStatementGroup} {SwitchLabel}}
SwitchBlockStatementGroup:
SwitchLabels BlockStatemens
SwitchLabel:
switch : le mot clé switch est suivi d’une expression mise en paramètre. Cette expression est
testée avec les différents cas. Il n’y a pas de limite théorique vis à vis du nombre de cases
dans une instruction switch.
case : le mot clé case est suivit par la valeur avec laquelle l’expression doit être comparée. Sa
valeur est du même type que celle de l’expression exécutée.
default: si aucun case ne correspond, on finira sur default (optionnel) qui exécutera le cas par
défaut. C’est l’équivalent du “else”. En général il est écrit en après le dernier case. Dans ce
cas, il ne sera pas suivi d’un break. Si il n’y a pas de default après le dernier case, le switch
passera à la prochaine instruction (une fois toutes les case parcourus).
break : le break permet de sortir du switch quand on passe dessus. Tant qu’il n’y a pas de
break, même si on a trouvé un case correspondant , on va executer les instructions du cas
suivant .
package [Link];
lass SwitchCaseExample {
public c
public static void main(String[] args) {
grading('A');
grading('C');
grading('E');
grading('G');
}
int success;
passTheCourse(success);
package [Link];
public class StringSwitchCase {
public static void main(String args[]) {
visitIsland("Santorini");
visitIsland("Crete");
visitIsland("Paros");
}
public static void visitIsland(String island) {
switch(island) {
case "Corfu":
[Link]("User wants to visit Corfu");
break;
case "Crete":
[Link]("User wants to visit Crete");
break;
case "Santorini":
[Link]("User wants to visit
Santorini");
break;
case "Mykonos":
[Link]("User wants to visit
Mykonos");
break;
default:
[Link]("Unknown Island");
break;
}
}
}
Output:
C’est un objet utilisé pour localiser un fichier, il est composé de nom de dossier et d’un nom
de fichier, ces noms et fichiers sont séparé par un séparateur(différent en fonction du
filesystem). Il représente généralement un chemin de fichier dépendant du système. Un
composant racine peut y être présent.
Exemple :
/Poudlard/Maison/Serpentard/[Link]
Un path est considéré vide si le path est constitué d’un élément nom (name) vide. Accéder à
un fichier avec un path vide est la même chose que se diriger vers le dossier par défaut du
système de fichier. (comme avec cd sur linux)
La classe paths est une classe contenant toutes les méthodes statique qui retourne un path.
Donc on peut créer un path.
Exemple :
import [Link];
import [Link];
}
}
37. Collection(s):
37.1. Définition :
Collection est une Interface qui représente une collection.
Une collection représente ensemble d’objets (ceux ci seront ses éléments).
- tous les éléments d’une collection sont de même type
Comme une collection n’admet que des objets, il est impossible d’y placer directement des
types primitifs. Pour baiser le système, on va utiliser des wrappers.
37.2.1. Collection :
Interface étendue par List. Elle reprend toutes méthodes de List telles que :
37.2.2. Collections :
Classe static correspondant à Collection. Elle permet d’appliquer des méthodes statiques en
rapport aux Collection
static <T> List<T> nCopies( int n, T o) : Returns an immutable list consisting of n
copies of the specified object.
Les méthodes de collections propose des service pour des collection.(comme les listes)
Cette classe possède aussi des algorithmes destructifs, ces algorithmes sont des
algorithmes qui modifient la collection qu’ils reçoivent (exemple tri), ils lanceront une
UnsupportedOperationException si la collection ne supporte pas l’opération, la
en binaire : 0x10
ne prend qu’un byte
en texte : 3136
le fichier fera 2 bytes car il stocke le 1 et le 6 et non un 16. Le 31 vient du fait que 1
dans le code unicode correspond au numéro 31 et le numéro 6 dans le code unicode
correspond au numéro 36.
java encode ses fichiers en unicode, l’unicode peut être encodé avec plusieurs encodage de
la norme UTF , comme ici utf8.
Exemple :
public enum Saisons {
PRINTEMPS, ÉTÉ, AUTOMNE, HIVER ;
}
39.3. Utilisation
L’énumération agit comme une classe. Elle peut avoir un constructeur, des attributs et des
méthodes. Les paramètres du constructeur (les valeurs de ces parametres) se placeront
entre parenthèses après chaque valeur de l’énumération.
Exemple :
public enum Saisons {
PRINTEMPS("pluie"), ÉTÉ("soleil"), AUTOMNE("pluie"),
HIVER("neige") ;
private String temps ;
public Saison(String temps) {
this.temps = temps ;
}
public String getTemps() {
return temps ;
}
}
[Link]()
Exemple :
[Link]() retournera la chaine « PRINTEMPS ».
Une méthode hashcode() est également fournie par défaut dans la classe Object. Si la
méthode equals() est Override, il faut également Override la méthode hashcode() vu que
ces deux méthodes sont étroitement liées.
Peu importe le nombre de fois que la méthode sera appelée sur un même objet durant une
exécution, la valeur du hashcode sera identique (consistante). Par contre elle pourra
changer d’une exécution à l’autre.
Deux objets égaux (donc avec la méthode equals() ) doivent retourner le même hashcode()
et ce peu importe le nombre de fois que la méthode est appelée sur ces objets (consistante)
(attention, les deux hashcode restent égaux mais la valeur du hashcode peut changer
d’une exécution à l’autre. La valeur du hashcode n’a pas d’importance, c’est l’égalité qui
l’est).
Par contre, il n’est pas nécessaire que deux objets différents retournent différents hashcode.
C’est mieux car cela améliore la performance mais ce n’est pas nécessaire.
41. Equals:
Ainsi, lors de la création d’une nouvelle classe, il est de bonne pratique de réécrire la
méthode equals (avec un @Override) pour l’adapter. Lorsque la méthode equals est
adaptée il ne faut pas oublier d’également adapter le hashcode().
41.2. Conventions/Utilisation
La méthode equals() doit être :
- réflexive : un objet est toujours égal à lui-même.
- symétrique : si a = b alors b = a.
- transitive : si a = b et b= c alors a = c.
- consistante : peu importe le nombre de fois que la méthode est utilisée sur les mêmes
objets, tant que ceux-ci ne sont pas modifiés le résultat de la méthode sera toujours le
même.
- gérer les null : tout est différent de null (et donc chaque fois que quelque chose est
comparé à null la méthode renverra false ou un nullPointerException). Deux null comparés
ensemble renverront également un nullPointerException ou un false. Pour comparer deux
null il vaut mieux utiliser “==”.
41.3. Exemple :
@Override
public boolean equals(Object o) {
// self check
if (this == o) {
return true;
}
// null check
if (o == null) {
return false;
}
//vérifie si pas même classe
if (getClass() != [Link]()) {
return false;
}
public Vehicle() {}
}
//The explanation of why the == can’t compare 2 strings is that the == operator compares the references of
the String objects rather than the values they store internally and it often also leads to unexpected and
unwanted behaviour.
42. Static :
Lorsqu’il est utilisé, cela indique que le membre en question appartient à la classe plutôt
qu’à une instance de la classe ; ce qui veut dire qu’un seul exemplaire du membre est créé
et partagé à travers toutes les instances de la classe.
Exemple :
public class Person {
private String firstName;
private String name;
public static int numberOfPeople;
public Person(String firstName, String name) {
this.firstName = firstName;
this.name = name;
numberOfPeople++;
}
}
Dans cet exemple, à chaque fois qu’une nouvelle personne est créée, la même copie de la
variable « numberOfPeople » est incrémentée.
Attention, les méthodes static ne peuvent pas être Override. En effet, elles sont lancées lors
de la compilation et un Override est utilisé lors de l’exécution (runtime polymorphisme).
Les méthodes abstract ne peuvent pas être static étant donné que le but d’une méthode
abstract est d’être Override (impossible donc avec une static).
Elles ne peuvent pas utiliser les mots-clefs this ou super (qui permettent d’utiliser la méthode
de la classe parente du même nom ou identifier une méthode entre 2 du même nom ; ce qui
n’a pas de sens dans un static étant donné qu’il n’y a qu’une seule méthode).
43. Import:
Toujours dans ce but d’amélioration de la lisibilité, il faut faire attention de ne pas avoir des
import inutiles.
Cas particulier : le package [Link] est importé implicitement. Les classes qui le
composent peuvent donc être utilisées directement sans devoir les importer.
43.2. Grammaire
Les import se placent au début du programme, après avoir (optionnel) déclaré le package
dans lequel la classe se trouve.
Il est possible d’importer une classe spécifique :
package monPackage;
import j[Link];
Ou un ensemble de classes :
Le caractère * étant un joker signifiant que toutes les classes du package [Link] doivent
être importées. C’est particulièrement utile si il est prévu d’utiliser plusieurs classes du
même package, sinon il vaut parfois mieux importer uniquement les classes dont on a
besoin pour éviter d’alourdir le programme.
Il est obligatoire de spécifier le nom du package que l’on souhaite importer, ‘import *’ ne
compilera pas.
Exemple :
import static [Link];
Cet import permet d’utiliser uniquement ‘PI’ dans la suite du code au lieu de ‘Math().PI’
Attention, le membre appelé doit être également static (voir static). De plus, ce type d’import
doit être utilisé avec parcimonie. Il est en effet parfois beaucoup plus parlant de spécifier le
nom complet d’une variable de classe.
44. Sérialisation :
44.1. Introduction
La sérialisation est la conversion de l’état d’un objet en un flux de byte; la désérialisation fait
l’opposé. Elle convertit un flux en l’état d’un objet. Formulé différemment, la sérialisation est
la conversion d’un objet java en une séquence static de byte qui peuvent être sauvegardé
dans une base de donnée ou transféré sur un réseau.
Ce mécanisme existe depuis les débuts de l’API Java I/O. Pour sérialiser un objet, il faut le
passer à une instance de ObjectOutputStream (l’objet doit préalablement implémenter
l’interface Serializable). Cependant cette interface ne possédant aucune méthode, il ne
faudra donc pas définir de code.
Si notre classe possède des champs non sérialisables, il faudra accompagner les attribut du
mot-clé transient (ça les retire du flux sérialiser et après être désérialiser, les champs seront
null.)
Tout wrapper est Serializable
// La classe String est Serializable, donc ces champs sont légaux.
private String nomEpisode, nomActeur1 ;
Pour des raisons d’optimisation , ne se trouve dans le flux sérialisé, que le minimum
d’information requis pour reconstruire l’objet. Typiquement, on y trouve donc :
le nom complet de la classe de l’objet
les noms de ses champs, et pour chacun de ces champs, son type et sa valeur
/ sérialization de l'objet
/
[Link](b);
44.3. Désérialisation :
// dans une méthode main
// on simplifie le code en retirant la gestion des exceptions
File fichier = new File("tmp/[Link]") ;
/ désérialisation de l'objet
/
BlackMirrorEp b = (BlackMirrorEp)[Link]() ;
[Link](b) ;
Si jamais notre classe a changé, ou que du moins son serialVersionUID a changé, alors
l'exception [Link] sera jetée.
Dans certains cas applicatifs, le mécanisme standard de sérialisation proposé par Java peut
se révéler inadapté, ou tout simplement ne pas convenir. Il est possible de le surcharger de
trois manières.
47.1. Modules:
Attention il faut télécharger les modules dans modules complémentaires!
47.2. Répartition :
Mettre en bleu les mots en cours d’écriture et barrer les mots finis (alt + Maj + 5). Si on a
besoin d’aide pour un mot, le mettre en rouge.
Si vous voyez des choses étranges ou expliqué étrangement, ajoutez un commentaire