0% ont trouvé ce document utile (0 vote)
11 vues65 pages

Cours Java

Ce document est un cours sur la programmation orientée objet en Java, destiné aux étudiants du Master CIBD. Il couvre des sujets variés tels que les concepts fondamentaux de Java, la gestion des exceptions, le multithreading, JDBC, et les fonctionnalités des versions récentes de Java. Le contenu est structuré en plusieurs sections, chacune abordant des aspects spécifiques du langage Java et de son utilisation.

Transféré par

hayoun fatimazahrae
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
11 vues65 pages

Cours Java

Ce document est un cours sur la programmation orientée objet en Java, destiné aux étudiants du Master CIBD. Il couvre des sujets variés tels que les concepts fondamentaux de Java, la gestion des exceptions, le multithreading, JDBC, et les fonctionnalités des versions récentes de Java. Le contenu est structuré en plusieurs sections, chacune abordant des aspects spécifiques du langage Java et de son utilisation.

Transféré par

hayoun fatimazahrae
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
Vous êtes sur la page 1/ 65

POO JAVA

Master CIBD

Pr. Lotfi ELAACHAK


Département Génie Informatique

2023 — 2024
Table des matières

1 Introduction 3
1.1 JAVA ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Avantages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 JAVA Vs C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 JRE, JDK et JVM ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.1 JVM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3.2 JRE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.3 JDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Garbage Collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4.1 Mark and Sweep Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 JAVA Oriénté Objet 8


2.1 Class et Objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.1 Constructeurs et Surcharge des constructeurs . . . . . . . . . . . . . . . . 9
2.1.2 Mot-clé static Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.1 Modificateurs de visibilitè en Java . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Heritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3.1 Types d’héritage en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5 Redéfinition / Override . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.6 Surcharge / Overload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.6.1 Mot clé Final en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.7 Classe abstraite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.7.1 Classe abstraite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.7.2 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.7.3 Abstract class Vs Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.8 Inner Class (Nested Classes) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3 Généricité, Collections et Exceptions 21


3.1 Généricité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.2 Collections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.2.1 List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.2 Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2.3 Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.2.4 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
3.2.5 HashTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2.6 Tri dans la collection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

1
3.3 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4 Multithreading avec Java 39


4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.2 Java Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.2.1 Algorithmes d’ordonnancement des threads . . . . . . . . . . . . . . . . . . 41
4.2.2 MultiThreads avec JAVA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.3 Java Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.3.1 Problème . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.4 Deadlock dans Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

5 Java et JDBC 49
5.1 Connection JDBC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.2 Le couple Statement – ResultSet . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.3 Les requêtes préparées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.4 La méthode executeUpdate() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.5 Limiter le nombre de connexion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
5.6 Gestion des transactions dans JDBC . . . . . . . . . . . . . . . . . . . . . . . . . 53

6 Les fonctionalités Java 8 , 9 et plus 56


6.1 Default méthodes sur les Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.1.1 Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.1.2 Default Methods et Héritage multiple . . . . . . . . . . . . . . . . . . . . . 58
6.2 Expressions Lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.3 API Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.3.1 Opérations intermédiaires : map . . . . . . . . . . . . . . . . . . . . . . . . 62
6.3.2 Opérations intermédiaires : filter . . . . . . . . . . . . . . . . . . . . . . . 62
6.3.3 Opérations intermédiaires : sorted . . . . . . . . . . . . . . . . . . . . . . . 62
6.3.4 Opérations terminaux : collect . . . . . . . . . . . . . . . . . . . . . . . . . 62
6.3.5 Opérations terminaux : forEach . . . . . . . . . . . . . . . . . . . . . . . . 63
6.3.6 Opérations terminaux : reduce . . . . . . . . . . . . . . . . . . . . . . . . . 63

Lotfi ELAACHAK Page 2


Chapitre 1
Introduction
1.1 JAVA ?
ava est un langage de programmation et une plate-forme. Java est un langage de programmation
de haut niveau, robuste, orienté objet et sécurisé.

Java a été développé par Sun Microsystems (aujourd’hui filiale d’Oracle) en 1995. James Gosling
est connu comme le père de Java. Avant Java, son nom était Oak. Comme Oak était déjà une
société enregistrée, James Gosling et son équipe ont changé le nom d’Oak en Java.

Plate-forme : Tout environnement matériel ou logiciel dans lequel un programme s’exécute est
appelé plateforme. Comme Java dispose d’un environnement d’exécution (JRE) et d’une API, il
s’agit d’une plate-forme.

Hello World
public class HelloWorld {

public static void main( String [] args ) {


System.out.println( "Hello World" );
}

Il existe 4 plateformes ou éditions de Java :


1. Java SE (Java Standard Edition) : Il s’agit d’une plateforme de programmation Java.
Elle comprend des API de programmation Java telles que java.lang, java.io, java.net,
java.util, java.sql, java.math, etc. Il comprend des sujets fondamentaux tels que la POO,
les chaînes de caractères, les expressions rationnelles, les exceptions, les classes internes, le
multithreading, les flux d’E/S, la mise en réseau, AWT, Swing, la réflexion, les collections,
etc.
2. Java EE (Java Enterprise Edition) : Il s’agit d’une plate-forme d’entreprise principalement
utilisée pour développer des applications web et d’entreprise. Elle est construite sur la
plate-forme Java SE. Elle comprend des sujets tels que Servlet, JSP, Web Services, EJB,
JPA, etc.
3. Java ME (Java Micro Edition) : Il s’agit d’une micro plate-forme dédiée aux applications
mobiles.
4. JavaFX : Il est utilisé pour développer des applications Internet riches. Il utilise une API
d’interface utilisateur légère.

1.1.1 Avantages
— Pas des pointeurs.

3
— Compilateur très strict car toutes les valeurs doivent être initialisées.
— Traitement des exceptions obligatoire.
— Les erreurs à l’exécution sont vérifiées tout comme les limites des tableaux.
— Sécurisé : Désallocation de la mémoire dynamique grâce au Garbage Collector
— Simple : Les points complexe dans c++ par exemple les pointeurs l’hiritage multiple ou
la surcharge des opérateures sont soit inexistants, soit traités implicitement en Java.
— Portable : Le compilateur Java génère du byte-code. Celui-ci constitue les instructions
pour la machine virtuelle JVM).

1.2 JAVA Vs C++


JAVA C++
C ++ est basé dur C avec extension orientée
Java est un vrai langage orienté objet.
objet.
Java ne supporte pas la surcharge d’opéra-
C ++ supporte la surcharge des opérateurs.
teur.
Java compilé en bytecode pour la machine C ++ généralement compilé en code ma-
virtuelle Java. chine.
Pas d’héritage multiple de classes, mais il
C ++ supporte l’héritage multiple de classes.
prend en charge l’interface.
Pas de variable globale. Chaque variable doit
C ++ supporte les variables globale.
déclarer dans la classe.
Java n’utilise pas les pointeurs C++ utilise les pointeurs
Nous devons utiliser le fichier header *.h en
Il n’y a pas de fichiers header *.h en Java.
C ++.

1.3 JRE, JDK et JVM ?

1.3.1 JVM
La JVM (Java Virtual Machine) est une machine abstraite. Elle est appelée machine virtuelle
parce qu’elle n’existe pas physiquement. Il s’agit d’une spécification qui fournit un environne-
ment d’exécution dans lequel le bytecode Java peut être exécuté. Elle peut également exécuter
les programmes écrits dans d’autres langages et compilés en bytecode Java.

Les JVM sont disponibles pour de nombreuses plates-formes matérielles et logicielles. La JVM, le
JRE et le JDK dépendent de la plate-forme car la configuration de chaque système d’exploitation
est différente. En revanche, Java est indépendant de la plate-forme. Il existe trois notions de JVM :
la spécification, l’implémentation et l’instance.newline
La JVM effectue les tâches principales suivantes :

— Chargement du code
— Vérification du code
— Exécution du code
— Fournit un environnement d’exécution

Lotfi ELAACHAK Page 4


1.3.2 JRE
JRE est l’acronyme de Java Runtime Environment (environnement d’exécution Java). Il est égale-
ment écrit Java RTE. L’environnement d’exécution Java est un ensemble d’outils logiciels utilisés
pour développer des applications Java. Il est utilisé pour fournir l’environnement d’exécution. Il
s’agit de l’implémentation de la JVM. Il existe physiquement. Il contient un ensemble de biblio-
thèques et d’autres fichiers que la JVM utilise au moment de l’exécution.

L’implémentation de la JVM est également diffusée activement par d’autres sociétés que Sun
Micro Systems.

1.3.3 JDK
JDK est l’acronyme de Java Development Kit (kit de développement Java). Le kit de dévelop-
pement Java (JDK) est un environnement de développement logiciel utilisé pour développer des
applications et des applets Java. Il existe physiquement. Il contient le JRE et les outils de déve-

Lotfi ELAACHAK Page 5


loppement.

Le JDK est une implémentation de l’une des plates-formes Java suivantes, publiées par Oracle
Corporation :
— Plate-forme Java édition standard
— Plate-forme Java édition entreprise
— Plate-forme Java Micro Edition
Le JDK contient une machine virtuelle Java (JVM) privée et quelques autres ressources telles
qu’un interpréteur/chargeur (java), un compilateur (javac), un archiveur (jar), un générateur de
documentation (Javadoc), etc. pour compléter le développement d’une application Java.

1.4 Garbage Collection


En Java, le garbage collection est le processus de gestion automatique de la mémoire. Il trouve
les objets inutilisés (qui ne sont plus utilisés par le programme) et les supprime pour libérer la
mémoire. Le mécanisme de garabge collector utilise plusieurs algorithmes de GC. L’algorithme
le plus populaire est Mark and Sweep.

— Il est contrôlé par un thread connu sous le nom de Garbage Collector.


— Java fournit deux méthodes System.gc() et Runtime.gc() qui envoient une requête à la
JVM pour le grabage collecteur .
— Les programmeurs Java sont libres de gérer la mémoire.
— Si la mémoire du tas est pleine, la JVM ne permettra pas de créer un nouvel objet et
affichera une erreur java.lang.OutOfMemoryError.
— Lorsque le Garbage collector supprime un objet de la mémoire, il appelle d’abord la
méthode finalize() de cet objet, puis le supprime.

1.4.1 Mark and Sweep Algorithm


La JVM Rockit utilise l’algorithme de marquage et de balayage pour effectuer le ramassage des
ordures. Cet algorithme comporte deux phases, la phase de marquage et la phase de balayage.

Lotfi ELAACHAK Page 6


Phase de Mark : Les objets accessibles à partir des threads, des handles natifs et d’autres sources
de GC sont marqués comme vivants. Chaque arbre d’objets a plus d’un objet racine. La racine
GC est toujours accessible. Ainsi, tout objet qui a une racine de Garbage collector à sa racine.
Elle identifie et marque tous les objets en cours d’utilisation, les autres pouvant être considérés
comme des déchets.

Phase de Sweep (Balayage) : Dans cette phase, le tas est parcouru pour trouver l’espace entre
les objets vivants. Ces espaces sont enregistrés dans la liste des objets libres et sont disponibles
pour l’allocation de nouveaux objets.

Il existe deux versions améliorées du Mark et du Sweep :


— le marquage et le balayage simultanés
— Marquage et balayage parallèles

Lotfi ELAACHAK Page 7


Chapitre 2
JAVA Oriénté Objet

2.1 Class et Objet

Class et Objet
class Account{
int acc_no;
String name;
float amount;
//Method to initialize object
void insert(int a,String n,float amt){

8
acc_no=a;
name=n;
amount=amt;
}
//deposit method
void deposit(float amt){
amount=amount+amt;
System.out.println(amt+" deposited");
}
//withdraw method
void withdraw(float amt){
if(amount<amt){
System.out.println("Insufficient Balance");
}else{
amount=amount-amt;
System.out.println(amt+" withdrawn");
}
}
//method to check the balance of the account
void checkBalance(){System.out.println("Balance is: "+amount);}
//method to display the values of an object
void display(){System.out.println(acc_no+" "+name+" "+amount);}
}
//Creating a test class to deposit and withdraw amount
class TestAccount{
public static void main(String[] args){
Account a1=new Account();
a1.insert(832345,"Ankit",1000);
a1.display();
a1.checkBalance();
a1.deposit(40000);
a1.checkBalance();
a1.withdraw(15000);
a1.checkBalance();

new Account().display();//anonymous object

}}

2.1.1 Constructeurs et Surcharge des constructeurs


En Java, un constructeur est un bloc de codes similaire à une méthode. Il est appelé lorsqu’une
instance de la classe est créée. Au moment de l’appel du constructeur, la mémoire de l’objet est
allouée dans la mémoire.

Lotfi ELAACHAK Page 9


Class et Constrecteurs
//Java program to overload constructors
class Student{
int id;
String name;
int age;
// default constuctor
Student(){
System.out.println("Default constructeur student")
}
//creating two arg constructor
Student(int i,String n){
id = i;
name = n;
}
//creating three arg constructor
Student(int i,String n,int a){
id = i;
name = n;
age=a;
}

Student(Student s){
id = s.id;
name =s.name;
}

void display(){System.out.println(id+" "+name+" "+age);}

public static void main(String args[]){


Student s1 = new Student5(111,"Karan");
Student s2 = new Student5(111,"Karan");
Student s3 = new Student5(222,"Aryan",25);
s2.display();
s3.display();

Lotfi ELAACHAK Page 10


Student s4 = new Student(s3);

s4.dispaly()
}
}

2.1.2 Mot-clé static Java


Le mot-clé static en Java est principalement utilisé pour la gestion de la mémoire. Nous pouvons
utiliser le mot-clé static avec des variables, des méthodes, des blocs et des classes imbriquées. Le
mot-clé static appartient à la classe et non à une instance de la classe.

Le mot-clé static peut être :


— une variable (également connue sous le nom de variable de classe)
— une méthode (également connue sous le nom de méthode de classe)
— un bloc
— Classe Nested / Inner class

Variable static
//Java Program to demonstrate the use of static variable
class Student{
int rollno;//instance variable
String name;
static String college ="ITS";//static variable
//constructor
Student(int r, String n){
rollno = r;
name = n;
}
//method to display the values
void display (){System.out.println(rollno+" "+name+" "+college);}
}
//Test class to show the values of objects
public class TestStaticVariable1{
public static void main(String args[]){
Student s1 = new Student(111,"Karan");

Lotfi ELAACHAK Page 11


Student s2 = new Student(222,"Aryan");
//we can change the college of all objects by the single line of code
//Student.college="BBDIT";
s1.display();
s2.display();
}
}

Methode static
//Java Program to demonstrate the use of a static method.
class Student{
int rollno;
String name;
static String college = "ITS";
//static method to change the value of static variable
static void change(){
college = "BBDIT";
}
//constructor to initialize the variable
Student(int r, String n){
rollno = r;
name = n;
}
//method to display values
void display(){System.out.println(rollno+" "+name+" "+college);}
}
//Test class to create and display the values of object
public class TestStaticMethod{
public static void main(String args[]){
Student.change();//calling change method
//creating objects
Student s1 = new Student(111,"Karan");
Student s2 = new Student(222,"Aryan");
Student s3 = new Student(333,"Sonoo");
//calling display method
s1.display();
s2.display();
s3.display();
}
}

Block static
class A2{
static{System.out.println("static block is invoked");}
public static void main(String args[]){
System.out.println("Hello main");

Lotfi ELAACHAK Page 12


}
}

2.2 Encapsulation
L’encapsulation en Java est un processus qui consiste à envelopper du code et des données dans
une unité unique, par exemple une capsule contenant plusieurs médicaments.

Nous pouvons créer une classe entièrement encapsulée en Java en rendant tous les membres de
la classe privés. Nous pouvons alors utiliser les méthodes setter et getter pour définir et obtenir
les données qu’elle contient.

La classe Java Bean est un exemple de classe entièrement encapsulée.

2.2.1 Modificateurs de visibilitè en Java


— Private : Le niveau d’accès d’un modificateur privé est limité à la classe. Il n’est pas
accessible depuis l’extérieur de la classe.
— Défaut : Le niveau d’accès d’un modificateur par défaut n’est accessible qu’à l’intérieur
du paquetage. Il n’est pas accessible depuis l’extérieur du paquetage. Si vous ne spécifiez
aucun niveau d’accès, il s’agira du niveau par défaut.
— Protected : Le niveau d’accès d’un modificateur protégé se situe à l’intérieur du paquetage
et à l’extérieur du paquetage par l’intermédiaire d’une classe enfant. Si vous ne créez pas
de classe enfant, il n’est pas possible d’y accéder depuis l’extérieur du paquetage.
— Public : Le niveau d’accès d’un modificateur public est partout. Il est accessible à l’inté-
rieur de la classe, à l’extérieur de la classe, à l’intérieur du paquetage et à l’extérieur du
paquetage.

2.3 Heritage
L’héritage en Java est un mécanisme par lequel un objet acquiert toutes les propriétés et tous les
comportements d’un objet parent. Il s’agit d’une partie importante des systèmes de programma-
tion orientés objets (OOP).

L’idée derrière l’héritage en Java est que vous pouvez créer de nouvelles classes qui sont construites
à partir de classes existantes. Lorsque vous héritez d’une classe existante, vous pouvez réutiliser
les méthodes et les champs de la classe mère. En outre, vous pouvez ajouter de nouvelles mé-
thodes et de nouveaux champs dans votre classe actuelle.

Heritage simple
class Employee{
float salary=40000;
}
class Programmer extends Employee{
int bonus=10000;
public static void main(String args[]){

Lotfi ELAACHAK Page 13


Programmer p=new Programmer();
System.out.println("Programmer salary is:"+p.salary);
System.out.println("Bonus of Programmer is:"+p.bonus);
}
}

2.3.1 Types d’héritage en Java

2.4 Polymorphism
Le polymorphisme signifie "plusieurs formes" et se produit lorsque nous avons plusieurs classes
qui sont liées les unes aux autres par l’héritage.

2.5 Redéfinition / Override


Si une sous-classe (classe enfant) possède la même méthode que celle déclarée dans la classe
parentale, il s’agit d’une surcharge de méthode en Java.

En d’autres termes, si une sous-classe fournit l’implémentation spécifique de la méthode qui a


été déclarée par l’une de ses classes parentes, il s’agit d’une surcharge de méthode.

Redifinition JAVA
class Vehicle{
//defining a method
void run(){System.out.println("Vehicle is running");}

Lotfi ELAACHAK Page 14


}
//Creating a child class
class Bike2 extends Vehicle{
//defining the same method as in the parent class
void run(){System.out.println("Bike is running safely");}

public static void main(String args[]){


Bike2 obj = new Bike2();//creating object
obj.run();//calling method
}
}

2.6 Surcharge / Overload


Si une classe possède plusieurs méthodes portant le même nom mais dont les paramètres sont
différents, on parle de surcharge de méthode.

Il existe deux façons de surcharger une méthode en Java


— En modifiant le nombre d’arguments
— En modifiant le type de données
Surcharge JAVA
class Adder{
static int add(int a,int b){return a+b;}
static int add(int a,int b,int c){return a+b+c;}
static double add(double a, double b){return a+b;}
}
class TestOverloading1{
public static void main(String[] args){
System.out.println(Adder.add(11,11));
System.out.println(Adder.add(11,11,11));
System.out.println(Adder.add(12.3,12.6));
}}

2.6.1 Mot clé Final en Java


Le mot-clé final en Java est utilisé pour restreindre l’utilisateur. Le mot-clé final en java peut
être utilisé dans de nombreux contextes. Final peut être :
1. variable
2. méthode
3. classe
Le mot-clé final peut être appliqué aux variables, une variable finale qui n’a pas de valeur est
appelée variable finale vierge ou variable finale non initialisée. Elle ne peut être initialisée que
dans le constructeur. La variable finale vide peut également être statique et sera initialisée dans
le bloc statique uniquement.

Lotfi ELAACHAK Page 15


Final JAVA
class Bike{
final int speedlimit=90;//final variable
void run(){
speedlimit=400;
}

final void start(){System.out.println("starting");}


public static void main(String args[]){
Bike9 obj=new Bike();
obj.run(); // run time error due to Final variable speedlimit
}
}//end of class

class Honda extends Bike{


void run(){System.out.println("running safely with 100kmph");}

public static void main(String args[]){


Honda honda= new Honda();
honda.start(); // rune time error due to Final method
}
}

final class Person{}

class Student extends Person{


void run(){System.out.println("running ");}

public static void main(String args[]){


Student s1= new Student(); // rune time error
s1.run();
}
}

Lotfi ELAACHAK Page 16


2.7 Classe abstraite

2.7.1 Classe abstraite


L’abstraction est un processus qui consiste à cacher les détails de la mise en œuvre et à ne mon-
trer que la fonctionnalité à l’utilisateur.

En d’autres termes, elle ne montre que les éléments essentiels à l’utilisateur et cache les détails
internes, par exemple, l’envoi de SMS où vous tapez le texte et envoyez le message. Vous ne
connaissez pas le traitement interne de la livraison du message.

— Une classe abstraite doit être déclarée avec le mot-clé abstract.


— Elle peut avoir des méthodes abstraites et non abstraites.
— Elle ne peut pas être instanciée.
— Elle peut avoir des constructeurs et des méthodes statiques.
— Elle peut avoir des méthodes finales qui obligent la sous-classe à ne pas modifier le corps
de la méthode.
Abstract Class
abstract class Shape{
Shape(){System.out.println("shap is created");}
abstract void draw();
}
//In real scenario, implementation is provided by others i.e. unknown by end user
class Rectangle extends Shape{
void draw(){System.out.println("drawing rectangle");}
}
class Circle1 extends Shape{
void draw(){System.out.println("drawing circle");}
}
//In real scenario, method is called by programmer or user
class TestAbstraction1{
public static void main(String args[]){
Shape s=new Circle1();//In a real scenario, object is provided through method, e.g
., getShape() method
s.draw();
}
}

2.7.2 Interface
En Java, une interface est un modèle de classe. Elle possède des constantes statiques et des mé-
thodes abstraites.

L’interface en Java est un mécanisme permettant de réaliser l’abstraction. Il ne peut y avoir que
des méthodes abstraites dans l’interface Java, pas de corps de méthode. Elle est utilisée pour
réaliser l’abstraction et l’héritage multiple en Java.

Lotfi ELAACHAK Page 17


En d’autres termes, on peut dire que les interfaces peuvent avoir des méthodes et des variables
abstraites. Elles ne peuvent pas avoir de corps de méthode.

— Elle ne peut pas être instanciée comme la classe abstraite.


— Depuis Java 8, on peut avoir des méthodes par défaut et statiques dans une interface.
— Depuis Java 9, nous pouvons avoir des méthodes privées dans une interface.
Interface JAVA
interface printable{
void print();
}

interface Showable{
void show();
}

interface Copiable extends printable{


void copy();
}

class A6 implements printable{


public void print(){System.out.println("Print");}

class A7 implements Printable,Showable{


public void print(){System.out.println("Print");}
public void show(){System.out.println("Show");}

class A4 implements Copiable{


public void print(){System.out.println("Print");}
public void copy(){System.out.println("Copy");}

public static void main(String args[]){


A6 obj = new A6();
obj.print();

A7 obj1 = new A7();


obj1.copy();

A4 obj1 = new A4();


obj4.print();
obj1.show();

}
}

Lotfi ELAACHAK Page 18


2.7.3 Abstract class Vs Interface
Abstract Interface
L’interface ne peut avoir que des méthodes
Une classe abstraite peut avoir des méthodes
abstraites. Depuis Java 8, elle peut également
abstraites et non abstraites.
avoir des méthodes par défaut et statiques.
La classe abstraite ne supporte pas l’héritage
L’interface supporte l’héritage multiple.
multiple.
La classe abstraite peut avoir des variables fi- L’interface n’a que des variables statiques et
nales, non finales, statiques et non statiques. finales.
La classe abstraite peut fournir l’implémen- L’interface ne peut pas fournir l’implémenta-
tation de l’interface. tion de la classe abstraite.
Le mot-clé abstract est utilisé pour déclarer Le mot-clé interface est utilisé pour déclarer
une classe abstraite. une interface.
Une classe abstraite peut étendre une autre
Une interface ne peut étendre qu’une autre
classe Java et implémenter plusieurs inter-
interface Java.
faces Java.
Une classe abstraite peut être étendue en uti- Une interface peut être implémentée en uti-
lisant le mot-clé "extends". lisant le mot-clé "implements".
Une classe abstraite Java peut avoir des
Les membres d’une interface Java sont pu-
membres de classe tels que private, protec-
blics par défaut.
ted, etc.

2.8 Inner Class (Nested Classes)


Une classe interne Java ou classe imbriquée est une classe déclarée à l’intérieur d’une classe ou
d’une interface.

Nous utilisons les classes internes pour regrouper logiquement les classes et les interfaces en un
seul endroit afin d’en faciliter la lecture et la maintenance.

En outre, elle peut accéder à tous les membres de la classe externe, y compris les méthodes et
les données privées.

inner class JAVA


class TestMemberOuter{
private int data=30;
class Inner{
void msg(){System.out.println("data is "+data);}
}
public static void main(String args[]){
TestMemberOuter obj=new TestMemberOuter1();
TestMemberOuter.Inner in=obj.new Inner();
in.msg();
}
}

Anonymous inner class JAVA

Lotfi ELAACHAK Page 19


abstract class Person{
abstract void eat();
}
class TestAnonymousInner{
public static void main(String args[]){
Person p=new Person(){
void eat(){System.out.println("nice fruits");}
};
p.eat();
}
}

Static inner class JAVA


class TestOuter{
static int data=30;
static class Inner{
void msg(){System.out.println("data is "+data);}
}
public static void main(String args[]){
TestOuter.Inner obj=new TestOuter.Inner();
obj.msg();
}
}

Lotfi ELAACHAK Page 20


3
Chapitre
Généricité, Collections et Exceptions
3.1 Généricité
L’introduction des généricité dans Java 5 a été le résultat d’un très long travail de spécifications,
étalé sur plus de cinq ans. Le but était de doter le langage Java d’un système de templates, à la
façon du C++, tout en conservant la compatibilité du byte code .
La première fonction de l’utilisation des génériques est d’éviter d’utiliser des méthodes détypées
dans une application, et de multiplier les casts d’Object vers les types que l’on manipule finale-
ment.

Avantages de la générique Java

1. Sécurité des types : Les objets génériques ne peuvent contenir qu’un seul type d’objet.
2. La fonte de type n’est pas nécessaire : Il n’est pas nécessaire de procéder à un typage.

Generic class JAVA


public class Area<T> {

// T is the Datatype like String,


// Integer of which Parameter type,
// the class Area is of
private T t;

public void add(T t)


{
// this.t specify the t variable inside
// the Area Class whereas the right hand
// side t simply specify the value as the
// parameter of the function add()
this.t = t;
}

public T get() { return t; }

public void getArea() {}

public static void main(String[] args)


{
// Object of generic class Area with parameter Type
// as Integer
Area<Integer> rectangle = new Area<Integer>();

21
// Object of generic class Area with parameter Type
// as Double
Area<Double> circle = new Area<Double>();
rectangle.add(10);
circle.add(2.5);
System.out.println(rectangle.get());
System.out.println(circle.get());
}
}

Generic with two templates


public class Pair<K, V> {

private K key;
private V value;

public Pair(K key, V value) {


this.key = key;
this.value = value;
}

public K getKey() { return key; }


public V getValue() { return value; }
}

3.2 Collections
La collection en Java est un cadre qui fournit une architecture pour stocker et manipuler un
groupe d’objets.

Les collections Java peuvent réaliser toutes les opérations que vous effectuez sur des données,
telles que la recherche, le tri, l’insertion, la manipulation et la suppression.

Une collection Java est une unité unique d’objets. Le cadre des collections Java fournit de nom-
breuses interfaces (Set, List, Queue, Deque) et classes (ArrayList, Vector, LinkedList, Priority-
Queueue, HashSet, LinkedHashSet, TreeSet).

Lotfi ELAACHAK Page 22


Méthod Description
static <T> int binary- Il recherche dans la liste l’objet spécifié et renvoie sa
Search() position dans une liste triée.
Permet d’inverser l’ordre des éléments dans la liste spé-
static void reverse()
cifiée.
static <T extends Compa-
Il est utilisé pour trier les éléments présents dans la liste
rable< super T> >void
spécifiée de la collection dans l’ordre croissant.
sort()
static <T> boolean repla- Permet de remplacer toutes les occurrences d’une valeur
ceAll() spécifiée dans une liste par l’autre valeur spécifiée.

3.2.1 List
List en Java permet de conserver une collection ordonnée. Elle contient des méthodes basées sur
un index pour insérer, mettre à jour, supprimer et rechercher les éléments. Elle peut également
contenir des éléments en double. Nous pouvons également stocker les éléments nuls dans la liste.

L’interface List se trouve dans le paquetage java.util et hérite de l’interface Collection. C’est une
fabrique de l’interface ListIterator. Grâce à ListIterator, nous pouvons itérer la liste en avant et
en arrière. Les classes d’implémentation de l’interface List sont ArrayList, LinkedList, Stack et
Vector. Les classes ArrayList et LinkedList sont largement utilisées dans la programmation Java.
La classe Vector est obsolète depuis Java 5.

ArrayList

La classe Java ArrayList utilise un tableau dynamique pour stocker les éléments. C’est comme
un tableau, mais il n’y a pas de limite de taille. Nous pouvons ajouter ou supprimer des éléments
à tout moment. Elle est donc beaucoup plus flexible qu’un tableau traditionnel. Il se trouve dans
le paquetage java.util. Il est semblable au vecteur en C++.

Lotfi ELAACHAK Page 23


La liste de tableaux de Java peut également contenir des éléments en double. Il implémente
l’interface List et nous pouvons donc utiliser toutes les méthodes de l’interface List. L’ArrayList
maintient l’ordre d’insertion en interne.

ArrayList
import java.util.*;
public class ArrayListExample2{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Traversing list through Iterator
Iterator itr=list.iterator();//getting the Iterator
while(itr.hasNext()){//check if iterator has the elements
System.out.println(itr.next());//printing the element and move to next
}

for(String fruit:list)
System.out.println(fruit);

System.out.println("Sorting numbers...");
//Creating a list of numbers
List<Integer> list2=new ArrayList<Integer>();
list2.add(21);
list2.add(11);
list2.add(51);
list2.add(1);
//Sorting the list
Collections.sort(list2);
//Traversing list through the for-each loop
for(Integer number:list2)
System.out.println(number);
}
}
}

LinkedList

La classe java LinkedList utilise une liste doublement liée pour stocker les éléments. Elle fournit
une structure de données de liste chaînée. Elle hérite de la classe AbstractList et met en œuvre
les interfaces List et Deque.

Lotfi ELAACHAK Page 24


Les points importants de la classe Java LinkedList sont les suivants :

— La classe Java LinkedList peut contenir des éléments en double.


— La classe Java LinkedList maintient l’ordre d’insertion.
— La classe Java LinkedList n’est pas synchronisée.
— Dans la classe Java LinkedList, la manipulation est rapide car aucun décalage n’est né-
cessaire.
— La classe Java LinkedList peut être utilisée comme une liste, une pile ou une file d’attente.

LinkedList
import java.util.*;
public class LinkedList1{
public static void main(String args[]){

LinkedList<String> al=new LinkedList<String>();


al.add("Ravi");
al.add("Vijay");
al.add("Ravi");
al.add("Ajay");

Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}

LinkedList with custumized object


import java.util.*;
class Book {
int id;
String name,author,publisher;
int quantity;
public Book(int id, String name, String author, String publisher, int quantity) {
this.id = id;
this.name = name;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
}
}
public class LinkedListExample {

Lotfi ELAACHAK Page 25


public static void main(String[] args) {
//Creating list of Books
List<Book> list=new LinkedList<Book>();
//Creating Books
Book b1=new Book(101,"Let us C","Yashwant Kanetkar","BPB",8);
Book b2=new Book(102,"Data Communications & Networking","Forouzan","Mc Graw
Hill",4);
Book b3=new Book(103,"Operating System","Galvin","Wiley",6);
//Adding Books to list
list.add(b1);
list.add(b2);
list.add(b3);
//Traversing list
for(Book b:list){
System.out.println(b.id+" "+b.name+" "+b.author+" "+b.publisher+" "+b.quantity)
;
}
}
}

ArrayList LinkedList
ArrayList utilise en interne un tableau dyna- LinkedList utilise en interne une liste double-
mique pour stocker les éléments. ment chainée pour stocker les éléments.
La manipulation avec ArrayList est lente car La manipulation avec LinkedList est plus ra-
elle utilise en interne un tableau. Si un élé- pide que ArrayList car elle utilise une liste
ment est retiré du tableau, tous les autres doublement liée, de sorte qu’aucun déplace-
éléments sont déplacés en mémoire. ment de bits n’est nécessaire en mémoire.
La classe LinkedList peut agir à la fois
Une classe ArrayList ne peut agir que comme
comme une liste et une file d’attente, car elle
une liste car elle n’implémente que List.
met en œuvre les interfaces List et Deque.
La classe ArrayList est plus adaptée au sto- La classe LinkedList est plus adaptée à la
ckage et à l’accès aux données. manipulation des données.
L’emplacement en mémoire des éléments L’emplacement des éléments d’une liste liée
d’une liste en tableau est contigu. n’est pas contigu.
Généralement, lors de l’initialisation d’une
ArrayList, une capacité par défaut de 10 est Dans une LinkedList, une liste vide est créée
attribuée à l’ArrayList. Il n’y a pas de cas de lorsqu’une LinkedList est initialisée.
capacité par défaut dans une liste chaînée.
Pour être précis, une ArrayList est un ta- LinkedList implémente la liste doublement
bleau redimensionnable. chaînée de l’interface list.

Stack

La pile est une structure de données linéaire utilisée pour stocker une collection d’objets. Elle est
basée sur le principe du dernier entré-premier sorti (LIFO). La structure de collecte Java fournit
de nombreuses interfaces et classes pour stocker la collection d’objets. L’une d’entre elles est la
classe Stack qui fournit différentes opérations telles que push, pop, search, etc.

Lotfi ELAACHAK Page 26


La structure de données de la pile comporte les deux opérations les plus importantes : push et
pop. L’opération push insère un élément dans la pile et l’opération pop retire un élément du
sommet de la pile. Voyons comment elles fonctionnent sur la pile.

Stack
import java.util.Stack;
public class StackEmptyMethodExample
{
public static void main(String[] args)
{
//creating an instance of Stack class
Stack<Integer> stk= new Stack<>();
// checking stack is empty or not
boolean result = stk.empty();
System.out.println("Is the stack empty? " + result);
// pushing elements into stack
stk.push(78);
stk.push(113);
stk.push(90);
stk.push(120);
//prints elements of the stack
System.out.println("Elements in Stack: " + stk);
result = stk.empty();
System.out.println("Is the stack empty? " + result);
}
}

Vector

Vector est comme un tableau dynamique qui peut augmenter ou diminuer sa taille. Contraire-
ment aux tableaux, il est possible de stocker un nombre indéfini d’éléments, car il n’y a pas de
limite de taille. Il fait partie de la structure Java Collection depuis Java 1.2. Il se trouve dans le
paquetage java.util et implémente l’interface List, de sorte que nous pouvons utiliser toutes les
méthodes de l’interface List.

Vector
import java.util.*;
public class VectorExample {
public static void main(String args[]) {
//Create a vector
Vector<String> vec = new Vector<String>();
//Adding elements using add() method of List
vec.add("Tiger");
vec.add("Lion");
vec.add("Dog");
vec.add("Elephant");

Lotfi ELAACHAK Page 27


//Adding elements using addElement() method of Vector
vec.addElement("Rat");
vec.addElement("Cat");
vec.addElement("Deer");

System.out.println("Elements are: "+vec);


}
}

3.2.2 Set
Set est une interface disponible dans le paquetage java.util. L’interface set étend l’interface Collec-
tion. Une collection ou une liste non ordonnée dans laquelle les doublons ne sont pas autorisés est
appelée interface Collection. L’interface set est utilisée pour créer un ensemble mathématique.
L’interface set utilise les méthodes de l’interface collection pour éviter l’insertion des mêmes
éléments. SortedSet et NavigableSet sont deux interfaces qui étendent l’implémentation des en-
sembles.

HashSet

La classe Java HashSet est utilisée pour créer une collection qui utilise une table de hachage pour
le stockage. Elle hérite de la classe AbstractSet et implémente l’interface Set.

Les points importants de la classe Java HashSet sont les suivants :

— HashSet stocke les éléments en utilisant un mécanisme appelé hachage.


— Le HashSet ne contient que des éléments uniques.
— Le HashSet autorise les valeurs nulles.
— La classe HashSet n’est pas synchronisée.
— La classe HashSet ne conserve pas l’ordre d’insertion. Ici, les éléments sont insérés sur la
base de leur code de hachage.
— HashSet est la meilleure approche pour les opérations de recherche.
HashSet
import java.util.*;
class HashSetExp{
public static void main(String args[]){
//Creating HashSet and adding elements
HashSet<String> set=new HashSet<String>();
set.add("Ravi");
set.add("Vijay");
set.add("Ravi");
set.add("Ajay");
//Traversing elements
Iterator<String> itr=set.iterator();
while(itr.hasNext()){
System.out.println(itr.next());

Lotfi ELAACHAK Page 28


}
}
}

HashSet form other collection


import java.util.*;
class HashSetExp{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();
list.add("Ravi");
list.add("Vijay");
list.add("Ajay");

HashSet<String> set=new HashSet(list);


set.add("Gaurav");
Iterator<String> i=set.iterator();
while(i.hasNext())
{
System.out.println(i.next());
}
}
}

TreeSet

La classe Java TreeSet met en œuvre l’interface Set qui utilise un arbre pour le stockage. Elle
hérite de la classe AbstractSet et implémente l’interface NavigableSet. Les objets de la classe
TreeSet sont stockés par ordre croissant.

Les points importants de la classe Java TreeSet sont les suivants :

— La classe Java TreeSet ne contient que des éléments uniques, comme HashSet.
— Les temps d’accès et de récupération de la classe Java TreeSet sont très rapides.
— La classe Java TreeSet n’autorise pas les éléments nuls.
— La classe Java TreeSet n’est pas synchronisée.
— La classe Java TreeSet maintient l’ordre croissant.
— La classe Java TreeSet ne contient que des éléments uniques, comme HashSet.
— Les temps d’accès et de récupération de la classe Java TreeSet sont assez rapides.
— La classe Java TreeSet n’autorise pas les éléments nuls.
— La classe Java TreeSet n’est pas synchronisée.
— La classe Java TreeSet maintient l’ordre croissant.
— Le TreeSet ne peut autoriser que les types génériques comparables.
TreeSet
import java.util.*;
class TreeSetExp{
public static void main(String args[]){
//Creating and adding elements

Lotfi ELAACHAK Page 29


TreeSet<String> al=new TreeSet<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ravi");
al.add("Ajay");
//Traversing elements
Iterator<String> itr=al.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}

Navigable Tree
import java.util.*;
class TreeSetExp{
public static void main(String args[]){
TreeSet<String> set=new TreeSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
System.out.println("Initial Set: "+set);

System.out.println("Reverse Set: "+set.descendingSet());

System.out.println("Head Set: "+set.headSet("C", true));

System.out.println("SubSet: "+set.subSet("A", false, "E", true));

System.out.println("TailSet: "+set.tailSet("C", false));


}
}

3.2.3 Queue
L’interface Queue est disponible dans le package java.util et étend l’interface Collection. Elle est
utilisée pour conserver les éléments qui sont traités selon la méthode FIFO (First In First Out).
Il s’agit d’une liste ordonnée d’objets, dans laquelle l’insertion d’éléments se fait à la fin de la
liste et la suppression d’éléments se fait au début de la liste.

Navigable Tree
import java.util.*;
class TestCollectionExp{

Lotfi ELAACHAK Page 30


public static void main(String args[]){

Queue<String> queue=new PriorityQueue<String>();


queue.add("Amit");
queue.add("Vijay");
queue.add("Karan");
queue.add("Jai");
queue.add("Rahul");

System.out.println("head:"+queue.element());
System.out.println("head:"+queue.peek());

System.out.println("iterating the queue elements:");


Iterator itr=queue.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}

queue.remove();
queue.poll();

System.out.println("after removing two elements:");


Iterator<String> itr2=queue.iterator();
while(itr2.hasNext()){
System.out.println(itr2.next());
}

}
}

3.2.4 Map
Map contient des valeurs sur la base d’une clé, c’est-à-dire une paire clé-valeur. Chaque paire de
clés et de valeurs est appelée entrée. Une carte contient des clés uniques.

Map est utile si on doit rechercher, mettre à jour ou supprimer des éléments sur la base d’une clé.

Map ne permet pas de dupliquer les clés, mais il est possible d’avoir des valeurs dupliquées.
HashMap et LinkedHashMap autorisent les clés et les valeurs nulles, mais TreeMap n’autorise
aucune clé ou valeur nulle.

Une Map ne peut pas être parcourue, vous devez donc la convertir en Set en utilisant les mé-
thodes keySet() ou entrySet().

Lotfi ELAACHAK Page 31


HashMap

La classe HashMap d’ava implémente l’interface Map qui nous permet de stocker des paires de
clés et de valeurs, où les clés doivent être uniques. Si vous essayez d’insérer une clé dupliquée, elle
remplacera l’élément de la clé correspondante. Il est facile d’effectuer des opérations en utilisant
l’index de la clé, comme la mise à jour, la suppression, etc. La classe HashMap se trouve dans le
paquetage java.util.

La classe HashMap en Java est semblable à la classe Hashtable héritée, mais elle n’est pas syn-
chronisée. Elle permet également de stocker les éléments nuls, mais il ne doit y avoir qu’une seule
clé nulle. Depuis Java 5, elle est désignée par HashMap<K,V>, où K représente la clé et V la
valeur. Elle hérite de la classe AbstractMap et implémente l’interface Map.

HashMap
import java.util.*;
public class MapExample {
public static void main(String[] args) {
Map map=new HashMap();
//Adding elements to map
map.put(1,"Amit");
map.put(5,"Rahul");
map.put(2,"Jai");
map.put(6,"Amit");
//Traversing Map
Set set=map.entrySet();//Converting to Set so that we can traverse
Iterator itr=set.iterator();
while(itr.hasNext()){
//Converting to Map.Entry so that we can get key and value separately
Map.Entry entry=(Map.Entry)itr.next();
System.out.println(entry.getKey()+" "+entry.getValue());
}

for(Map.Entry m:map.entrySet()){
System.out.println(m.getKey()+" "+m.
getValue());
}
}
}

TreeMap

La classe Java TreeMap est une implémentation basée sur un arbre rouge-noir. Elle fournit un
moyen efficace de stocker des paires clé-valeur dans un ordre trié.

— Java TreeMap contient des valeurs basées sur la clé. Elle met en œuvre l’interface Navi-
gableMap et étend la classe AbstractMap.
— Java TreeMap ne contient que des éléments uniques.

Lotfi ELAACHAK Page 32


— La Java TreeMap ne peut pas avoir de clé nulle mais peut avoir plusieurs valeurs nulles.
— Java TreeMap n’est pas synchronisé.
— Java TreeMap maintient l’ordre croissant.
HashMap
import java.util.*;
class TreeMapExp{
public static void main(String args[]){
TreeMap<Integer,String> map=new TreeMap<Integer,String>();
map.put(100,"Amit");
map.put(102,"Ravi");
map.put(101,"Vijay");
map.put(103,"Rahul");

for(Map.Entry m:map.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}

3.2.5 HashTable
La classe ava Hashtable implémente une table de hachage, qui associe des clés à des valeurs. Elle
hérite de la classe Dictionary et implémente l’interface Map.

— Une table de hachage est un tableau de listes. Chaque liste est appelée "bucket". La position
du seau est identifiée en appelant la méthode hashcode(). Une table de hachage contient
des valeurs basées sur la clé.
— La classe Java Hashtable contient des éléments uniques.
— La classe Table de hachage Java n’autorise pas les clés ou les valeurs nulles.
— La classe Hashtable Java est synchronisée.
HashTable
import java.util.*;
class HashtableExp{
public static void main(String args[]){
Hashtable<Integer,String> hm=new Hashtable<Integer,String>();

hm.put(100,"Amit");
hm.put(102,"Ravi");
hm.put(101,"Vijay");
hm.put(103,"Rahul");

for(Map.Entry m:hm.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}

Lotfi ELAACHAK Page 33


3.2.6 Tri dans la collection
Interface comparable Java

L’interface Java Comparable est utilisée pour ordonner les objets de la classe définie par l’utili-
sateur. Cette interface se trouve dans le paquetage java.lang et ne contient qu’une seule méthode
appelée compareTo(Object). Elle ne fournit qu’une seule séquence de tri, c’est-à-dire que vous
pouvez trier les éléments sur la base d’un seul membre de données. Par exemple, il peut s’agir
d’un numéro de rôle, d’un nom, d’un âge ou de toute autre donnée.

public int compareTo(Object obj) : Cette méthode permet de comparer l’objet actuel à l’objet
spécifié. Elle renvoie

— Un nombre entier positif, si l’objet courant est plus grand que l’objet spécifié.
— Un nombre entier négatif, si l’objet courant est inférieur à l’objet spécifié.
— Zéro, si l’objet courant est égal à l’objet spécifié.
Tri des objets (Comparable)
import java.util.*;

class Student implements Comparable<Student> {


public String name;
public Student(String name) {
this.name = name;
}
public int compareTo(Student person) {
return name.compareTo(person.name);

}
}
public class TestSortExp {
public static void main(String[] args) {
ArrayList<Student> al=new ArrayList<Student>();
al.add(new Student("Viru"));
al.add(new Student("Saurav"));
al.add(new Student("Mukesh"));
al.add(new Student("Tahir"));

Collections.sort(al);
for (Student s : al) {
System.out.println(s.name);
}
}
}

Lotfi ELAACHAK Page 34


Interface du Comprator Java

L’interface Java Comparator est utilisée pour ordonner les objets d’une classe définie par l’utili-
sateur.

Cette interface se trouve dans le paquet java.util et contient deux méthodes : compare(Object
obj1,Object obj2) et equals(Object element).

Elle fournit plusieurs séquences de tri, c’est-à-dire que vous pouvez trier les éléments sur la base
de n’importe quel membre de données, par exemple, rollno, nom, âge ou autre.

Tri des objets (Comparator)


import java.util.*;

class Student{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
}

import java.util.*;
class AgeComparator implements Comparator{
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;

if(s1.age==s2.age)
return 0;
else if(s1.age>s2.age)
return 1;
else
return -1;
}
}

import java.util.*;
class NameComparator implements Comparator{
public int compare(Object o1,Object o2){
Student s1=(Student)o1;
Student s2=(Student)o2;

return s1.name.compareTo(s2.name);

Lotfi ELAACHAK Page 35


}
}

import java.util.*;
import java.io.*;

class Simple{
public static void main(String args[]){

ArrayList al=new ArrayList();


al.add(new Student(101,"Vijay",23));
al.add(new Student(106,"Ajay",27));
al.add(new Student(105,"Jai",21));

System.out.println("Sorting by Name");

Collections.sort(al,new NameComparator());
Iterator itr=al.iterator();
while(itr.hasNext()){
Student st=(Student)itr.next();
System.out.println(st.rollno+" "+st.name+" "+st.age);
}

System.out.println("Sorting by age");

Collections.sort(al,new AgeComparator());
Iterator itr2=al.iterator();
while(itr2.hasNext()){
Student st=(Student)itr2.next();
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}

3.3 Exceptions
Une exception est une erreur se produisant dans un programme qui conduit le plus souvent à
l’arrêt de celui-ci. Le fait de gérer les exceptions s’appelle aussi « la capture d’exception ». Le
principe consiste à repérer un morceau de code (par exemple, une division par zéro) qui pourrait
générer une exception, de capturer l’exception correspondante et enfin de la traiter, c’est-à-dire
d’afficher un message personnalisé et de continuer l’exécution.
Les exceptions représentent le mécanisme de gestion des erreurs intégré au langage Java. Il se
compose d’objets représentant les erreurs et d’un ensemble de trois mots clés qui permettent de
détecter et de traiter ces erreurs ( try, catch et finally ) et de les lever ou les propager (throw et
throws).

Lotfi ELAACHAK Page 36


Lors de la détection d’une erreur, un objet qui hérite de la classe Exception est créé (on dit
qu’une exception est levée) et propagé à travers la pile d’exécution jusqu’à ce qu’il soit traité.
Ces mécanismes permettent de renforcer la sécurité du code Java.

mots-clés Description
Le mot-clé "try" est utilisé pour spécifier un bloc dans
lequel nous devons placer un code d’exception. Cela si-
try
gnifie que nous ne pouvons pas utiliser le bloc try seul.
Le bloc try doit être suivi par catch ou finally.
Le bloc "catch" est utilisé pour gérer l’exception. Il doit
être précédé du bloc try, ce qui signifie que nous ne pou-
catch
vons pas utiliser le bloc catch seul. Il peut être suivi plus
tard par le bloc finally.
Le bloc "finally" est utilisé pour exécuter le code néces-
finally saire du programme. Il est exécuté qu’une exception soit
gérée ou non.
throw Le mot-clé "throw" est utilisé pour lancer une exception.
Le mot-clé "throws" est utilisé pour déclarer des excep-
tions. Il spécifie qu’une exception peut se produire dans
throws
la méthode. Il ne lance pas d’exception. Il est toujours
utilisé avec la signature de la méthode.

Lotfi ELAACHAK Page 37


Exception
public class JavaExceptionExample{
public static void main(String args[]){
try{
//code that may raise exception
int data=100/0;
}catch(ArithmeticException e){System.out.println(e);}
//rest code of the program
System.out.println("rest of the code...");
}
}

Exception
class TestFinallyBlock {
public static void main(String args[]){
try{
//below code do not throw any exception
int data=25/5;
System.out.println(data);
}
//catch won't be executed
catch(NullPointerException e){
System.out.println(e);
}
//executed regardless of exception occurred or not
finally {
System.out.println("finally block is always executed");
}

System.out.println("rest of phe code...");


}
}

Lotfi ELAACHAK Page 38


Chapitre 4
Multithreading avec Java
4.1 Introduction
Le multithreading en Java est un processus d’exécution simultanée de plusieurs threads.

Un thread est un sous-processus léger, la plus petite unité de traitement. Le multiprocessus et le


multithreading sont tous deux utilisés pour réaliser le multitâche.

Cependant, nous utilisons le multithreading plutôt que le multiprocessing parce que les threads
utilisent une zone de mémoire partagée. Ils n’allouent pas de zone de mémoire séparée, ce qui
permet d’économiser de la mémoire, et le changement de contexte entre les threads prend moins
de temps que le processus.

Le multithreading Java est principalement utilisé dans les jeux, les animations, etc.

Les threads sont indépendants. Si une exception se produit dans un thread, elle n’affecte pas les
autres threads. Ils utilisent une zone de mémoire partagée.

1. Il ne bloque pas l’utilisateur parce que les threads sont indépendants et qu’il est possible
d’effectuer plusieurs opérations en même temps.
2. Il est possible d’effectuer plusieurs opérations en même temps, ce qui permet de gagner
du temps.
3. Les threads étant indépendants, les autres threads ne sont pas affectés si une exception se
produit dans un seul thread.

Comme le montre la figure ci-dessus, un thread est exécuté à l’intérieur du processus. Il y a un


changement de contexte entre les threads. Il peut y avoir plusieurs processus dans le système
d’exploitation, et un processus peut avoir plusieurs threads.

39
4.2 Java Threads
Il existe deux façons de créer un fil de discussion :
— En étendant la classe Thread
— En implémentant l’interface Runnable.

Thread Class

Thread Class
class Multi extends Thread{
public void run(){
System.out.println("thread is running...");
}

public static void main(String args[]){


Multi t1=new Multi();
t1.start();
}
}

Runnable Interface

Runnable Interface
class Multi3 implements Runnable{
public void run(){
System.out.println("thread is running...");
}

public static void main(String args[]){


Multi3 m1=new Multi3();
Thread t1 =new Thread(m1); // Using the
constructor Thread(Runnable r)
t1.start();
}
}

Lotfi ELAACHAK Page 40


4.2.1 Algorithmes d’ordonnancement des threads
Dans cet algorithme d’ordonnancement, le planificateur choisit les threads qui arrivent en pre-
mier dans la file d’attente d’exécution.

4.2.2 MultiThreads avec JAVA

MultiThreads (Class)
public class TestThread extends Thread {
public TestThread(String name){
super(name);
}
public void run(){
for(int i = 0; i < 10; i++)
System.out.println(this.getName());
}
}

Lotfi ELAACHAK Page 41


public class Test {
public static void main(String[] args) {
TestThread t = new TestThread("A");
TestThread t2 = new TestThread(" B");
t.start();
t2.start();
}
}

MultiThreads (Interface)

public class AutreBateau implements Runnable {

// implémentation de la méthode run() de l'interface Runnable


public void run() {

int n = 0 ;
while (n++ < 100) {
System.out.println("Je vogue aussi !") ;
try {

Thread.sleep(10) ;
} catch (InterruptedException e) {

// gestion de l'erreur
}
}
}

public static void main(String[] args) {


// dans une méthode main()
// instanciantion d'un objet de type Runnable
AutreBateau autreBateau = new AutreBateau() ;

// construction d'un Thread en passant cette instance de Runnable en paramètre


Thread thread = new Thread(autreBateau) ;

// lancement de ce thread par appel à sa méthode start()


thread.start() ;

// cette méthode rend immédiatement la main...


System.out.println("Thread lancé") ;

Lotfi ELAACHAK Page 42


L’ordre d’exécution est souvent aléatoire, car Java utilise un ordonnanceur. Ce qu’il faut retenir
c’est que si on utilise plusieurs threads dans une application, ceux-ci ne s’exécutent pas toujours
en même temps ! En fait, l’ordonnanceur gère les threads de façon aléatoire.

Le pool de threads Java représente un groupe de threads de travail qui attendent le travail et qui
sont réutilisés plusieurs fois.
Dans le cas d’un pool de threads, un groupe de threads de taille fixe est créé. Un thread du pool
de threads est extrait et se voit attribuer une tâche par le fournisseur de services. Une fois la
tâche terminée, le thread est à nouveau contenu dans le pool de threads.

MultiThreads (Pool)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class WorkerThread implements Runnable {
private String message;
public WorkerThread(String s){
this.message=s;
}
public void run() {
System.out.println(Thread.currentThread().getName()+" (Start) message = "+
message);
processmessage();//call processmessage method that sleeps the thread for 2
seconds
System.out.println(Thread.currentThread().getName()+" (End)");//prints
thread name
}
private void processmessage() {
try { Thread.sleep(2000); } catch (InterruptedException e) { e.
printStackTrace(); }
}
}

public class TestThreadPool {


public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);//creating a
pool of 5 threads
for (int i = 0; i < 10; i++) {
Runnable worker = new WorkerThread("" + i);
executor.execute(worker);//calling execute method of ExecutorService
}
executor.shutdown();
while (!executor.isTerminated()) { }

System.out.println("Finished all threads");


}
}

Lotfi ELAACHAK Page 43


MultiThreads (Case of Study)
import java.awt.*;
import java.awt.event.*;

class Bouncing_Balls
extends Frame implements MouseListener {
// initializing co-ordinates
int x = 40, y = 40, t1 = 1, t2 = 1;
int x1 = 200, y1 = 40, t12 = 1, t22 = 1;
int x2 = 100, y2 = 100, t13 = 1, t23 = 1;
Thread th;

// Making constructor
Bouncing_Balls()
{
setSize(700, 800);
setVisible(true);

// Creating a new Thread


th = new Thread(new Thread() {
public void run()
{
while (true) {
x = x + t1;
y = y + t2;
x1 = x1 + t12;
y1 = y1 + t22;
x2 = x2 - t13;
y2 = y2 - t23;

// specifying some condition to make


// balls move in a particular path
if (x < 0 || x > 680)
t1 = t1 * (-1);
if (y < 20 || y > 780)
t2 = t2 * (-1);
if (x1 < 0 || x1 > 680)
t12 = t12 * (-1);
if (y1 < 20 || y1 > 780)
t22 = t22 * (-1);
if (x2 < 0 || x2 > 680)
t13 = t13 * (-1);
if (y2 < 20 || y2 > 780)
t23 = t23 * (-1);

try {

Lotfi ELAACHAK Page 44


// Calling sleep method
this.sleep(5);
}
catch (Exception E) {
}
repaint();
}
}
});
addMouseListener(this);
}

public void mouseClicked(MouseEvent M)


{
// Thread will start when mouse is clicked
th.start();
}
public void mousePressed(MouseEvent M) {}
public void mouseReleased(MouseEvent M) {}
public void mouseEntered(MouseEvent M) {}
public void mouseExited(MouseEvent M) {}

public void paint(Graphics g)


{
g.setColor(Color.pink);
g.fillOval(x, y, 40, 40);
g.setColor(Color.pink);
g.fillOval(x1, y1, 40, 40);
g.setColor(Color.pink);
g.fillOval(x2, y2, 40, 40);
}
public static void main(String[] args)
{
Bouncing_Balls B = new Bouncing_Balls();
}
}

4.3 Java Synchronization


La synchronisation en Java est la capacité de contrôler l’accès de plusieurs threads à une res-
source partagée.

La synchronisation Java est la meilleure option lorsque nous voulons permettre à un seul thread
d’accéder à la ressource partagée.

Lotfi ELAACHAK Page 45


— Pour éviter les interférences entre les fils.
— Pour éviter les problèmes de cohérence.

4.3.1 Problème
problème d’utilisation du Threads non synchronisés pour acceder à un resource paratgée est la
non consistence des sortie (Access concurrent)

No Synchronization
public synchronized void withdraw (int amount)
{
if (amount <= balance)
{
balance -= amount;
System.out.println ("Compte débité de " + amount + " euros");
}
}

Supposons que User1 a commencé à exécuter la méthode withdraw, elle vient d’évaluer la condi-
tion du if. À ce moment, le scheduler décide d’arrêter User1 et de laisser User2 s’exécuter. Ce
dernier va donc tenter d’appeler la méthode withdraw, mais comme User1 est déjà occupée de-
dans, User2 va passer dans l’état bloqué, et ce jusqu’à ce que User1 ait fini d’exécuter la méthode.

Lock

Tous les objets possèdent un built-in lock. Ce lock est nécessaire à un thread qui souhaite accéder
à une méthode marquée synchronized. Un thread d’exécution va pouvoir prendre le lock d’un
objet, et une fois cela fait, il va pouvoir entrer librement dans toutes les méthodes marquées
synchronized. Une fois que le thread a terminé, il rend le lock de l’objet. Lorsqu’un thread tente
d’exécuter une méthode marquée synchronized, deux cas peuvent se produire. Soit le lock de
l’objet sur lequel la méthode est appelée est encore disponible et dans ce cas, le thread s’empare
du lock et peut exécuter la méthode. Dans l’autre cas, le lock a déjà été pris et le thread est
bloqué, en attente de la libération du lock.

No Synchronization
class Table{
void printTable(int n){//method not synchronized
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}

Lotfi ELAACHAK Page 46


class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}

}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}

class TestSynchronization1{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}

Solution ajout de mot-clé Synchronized à la mléthode à accees conccurent.


with Synchronization
class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}

}
}

the same code above

Lotfi ELAACHAK Page 47


4.4 Deadlock dans Java
Le Deadlock (Blocage)en Java fait partie du multithreading. Un blocage peut se produire lors-
qu’un thread attend un verrou d’objet acquis par un autre thread et qu’un second thread attend
un verrou d’objet acquis par le premier thread. Étant donné que les deux threads attendent l’un
et l’autre de libérer le verrou, on parle de Deadlock.

Le mot-clé synchronized est utilisé pour rendre la classe ou la méthode thread-safe, ce qui signifie
qu’un seul thread peut avoir le verrou de la méthode synchronisée et l’utiliser, les autres threads
doivent attendre que le verrou se libère et que l’un d’entre eux acquière ce verrou.

Il est important de l’utiliser si notre programme s’exécute dans un environnement multithread


où deux threads ou plus s’exécutent simultanément. Mais il arrive aussi qu’elle pose un problème
appelé "Deadlock".

Lotfi ELAACHAK Page 48


Chapitre 5
Java et JDBC
JDBC est l’acronyme de Java Database Connectivity (connectivité de base de données Java).
JDBC est une API Java qui permet de se connecter à la base de données et d’y exécuter des
requêtes. Elle fait partie de JavaSE (Java Standard Edition). L’API JDBC utilise des pilotes
JDBC pour se connecter à la base de données. Il existe quatre types de pilotes JDBC :
— Pilote de pont JDBC-ODBC,
— Pilote natif,
— Pilote de protocole réseau
— Pilote léger

Les types de pilotes JDBC

— Des drivers JDBC de type 1 : JDBC-ODBC, ce type utilise l’interface ODBC pour se
connecter à une base de données (on en a déjà parlé) ; au niveau de la portabilité, on
trouve mieux ;
— Des drivers JDBC de type 2 : ils intègrent les pilotes natifs et les pilotes Java ; en fait,
la partie Java traduit les instructions en natif afin d’être comprises et interprétées par les
pilotes natifs ;
— Des drivers JDBC de type 3 : écrit entièrement en Java, ce type convertit les appels
en un langage totalement indépendant du SGBD ; un serveur intégré traduit ensuite les
instructions dans le langage souhaité par le SGBD ;
— Des drivers JDBC de type 4 : des pilotes convertissant directement les appels JDBC en
instructions compréhensibles par le SGBD ; ce type de drivers est codé et proposé par les
éditeurs de BDD.
La version actuelle de JDBC est basée sur l’interface de niveau d’appel X/Open SQL. Le pa-
quetage java.sql contient des classes et des interfaces pour l’API JDBC. Une liste des interfaces
populaires de l’API JDBC est donnée ci-dessous :
— Driver interface
— Connection interface
— Statement interface
— PreparedStatement interface
— CallableStatement interface
— ResultSet interface
— ResultSetMetaData interface
— DatabaseMetaData interface
— RowSet interface

49
5.1 Connection JDBC

JDBC Connection
public class Connect {
public static void main(String[] args) {
try {
Class.forName("org.postgresql.Driver"); System.out.println("Driver O.K.");
String url = "jdbc:postgresql://localhost:5432/Ecole"; String user = "postgres";
String passwd = "postgres";
Connection conn = DriverManager.getConnection(url, user, passwd); System.out.
println("Connexion effective !");
} catch (Exception e) {

e.printStackTrace();
}
}}

5.2 Le couple Statement – ResultSet


Voici deux objets que vous utiliserez sûrement beaucoup ! En fait, ce sont ces deux objets qui
permettent de récupérer des données de la BDD.
Pour exécuter une requête SQL via JDBC il faut suivre 4 étapes :

— Création de l’objet Statement ;


— Exécution de la requête SQL ;
— Récupération et affichage des données via l’objet ResultSet ;
— Fermeture des objets utilisés (bien que non obligatoire, c’est recommandé).

L’objet Statement permet d’exécuter des instructions SQL, il interroge la base de données et
retourne les résultats. Ensuite, ces résultats sont stockés dans l’objet ResultSet, grâce auquel on
peut parcourir les lignes de résultats et les afficher.
JDBC Statment et ResultSet
public class Connect {
public static void main(String[] args) {
try {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/Ecole"; String user = "postgres";
String passwd = "postgres";
Connection conn = DriverManager.getConnection(url, user, passwd);
//Création d'un objet Statement
Statement state = conn.createStatement();
//L'objet ResultSet contient le résultat de la requête SQL ResultSet result = state
.executeQuery("SELECT * FROM classe"); //On récupère les MetaData
ResultSetMetaData resultMeta = result.getMetaData();

Lotfi ELAACHAK Page 50


System.out.println("\n**********************************"); //On affiche le nom des
colonnes
for(int i = 1; i <= resultMeta.getColumnCount(); i++)
System.out.print("\t" + resultMeta.getColumnName(i).toUpperCase() + "\t *");
System.out.println("\n**********************************");
while(result.next()){
for(int i = 1; i <= resultMeta.getColumnCount(); i++)
System.out.print("\t" + result.getObject(i).toString() + "\t |"); System.out.
println("\n---------------------------------");
}
result.close();
state.close();
} catch (Exception e) {
e.printStackTrace();
} }
}

5.3 Les requêtes préparées


L’interface PreparedStatement définit les méthodes pour un objet qui va encapsuler une requête
précompilée. Ce type de requête est particulièrement adapté pour une exécution répétée d’une
même requête avec des paramètres différents. Cette interface hérite de l’interface Statement.
Lors de l’utilisation d’un objet de type PreparedStatement, la requête est envoyée au moteur de
la base de données pour que celui-ci prépare son exécution.
JDBC Prepared Statment
public class Prepare {
public static void main(String[] args) {
try {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/
Ecole"; String user = "postgres";
String passwd = "postgres";
Connection conn = DriverManager.
getConnection(url, user, passwd);
Statement state = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
//On crée la requête
String query = "SELECT prof_nom,
prof_prenom FROM professeur"; //Premier trou pour le nom du professeur
query += " WHERE prof_nom = ?";
//Deuxième trou pour l'identifiant
du professeur
query += " OR prof_id = ?";

Lotfi ELAACHAK Page 51


System.out.println(prepare.toString());
//On modifie le premier trou
prepare.setString(1, "TOTO");
//On affiche à nouveau la requête exécutée
System.out.println(prepare.toString()); //
On modifie le deuxième trou
prepare.setInt(2, 159753);
//On affiche une nouvelle fois la
requête exécutée
System.out.println(prepare.toString());
prepare.close();
state.close();
} catch (Exception e) {
e.printStackTrace();
} }

5.4 La méthode executeUpdate()


Lorsque la méthode executeUpdate() est utilisée pour exécuter un traitement de type DDL (
Data Definition Langage : définition de données ) comme la création d’un table, elle retourne 0.
Si la méthode retourne 0, cela peut signifier deux choses : le traitement de mise à jour n’a affecté
aucun enregistrement ou le traitement concernait un traitement de type DDL.

JDBC Execute Update


state.executeUpdate("INSERT INTO professeur (prof_nom, prof_prenom) VALUES('SALMON
', 'Dylan')");
state.executeUpdate("DELETE FROM professeur WHERE prof_nom = 'MAMOU'");

5.5 Limiter le nombre de connexion


Parmi les moyens d’optimiser le code et le fonctionnement de l’application et d’ouvrir la connexion
avec le serveur de BDD est une seul fois au cours d’exécution de l’application, et d’éviter de ré-
initialiser la connexion à la BDD chaque fois qu’on est besoin de faire une transaction avec.
Ce mécanisme est garantie avec l’implémentation d’un patron de conception Singleton.

JDBC Singleton
public class SdzConnection{
//URL de connexion
private String url = "jdbc:postgresql://localhost:5432/Ecole"; //Nom du user
private String user = "postgres";
//Mot de passe de l'utilisateur
private String passwd = "postgres";
//Objet Connection
private static Connection connect;

Lotfi ELAACHAK Page 52


//Constructeur privé
private SdzConnection(){
try {
connect = DriverManager.getConnection(url, user, passwd);
} catch (SQLException e) {
e.printStackTrace();
} }
//Méthode qui va nous retourner notre instance et la créer si elle n'existe pas
public static Connection getInstance(){ if(connect == null){
new SdzConnection();
}
return connect;
}
}

5.6 Gestion des transactions dans JDBC


La transaction représente une unité de travail unique.

Les propriétés ACID décrivent bien la gestion des transactions. ACID signifie Atomicité, Cohé-
rence, Isolation et Durabilité.

L’atomicité signifie que toutes les transactions sont réussies ou qu’aucune ne l’est.

La cohérence permet d’amener la base de données d’un état cohérent à un autre état cohérent.

L’isolation garantit que la transaction est isolée des autres transactions.

La durabilité signifie qu’une fois qu’une transaction a été validée, elle le restera, même en cas
d’erreurs, de coupure de courant, etc.

Avantages de la gestion des transactions sont les performances rapides.

Les Methodes pour la gestion des Transactions :

Lotfi ELAACHAK Page 53


— void setAutoCommit(boolean status) Il est vrai par défaut, ce qui signifie que chaque
transaction est validée par défaut.
— void commit() valide la transaction.
— void rollback() annule la transaction.
Transactions
import java.sql.*;
import java.io.*;
class TM{
public static void main(String args[]){
try{

Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","
system","oracle");
con.setAutoCommit(false);

PreparedStatement ps=con.prepareStatement("insert into user420 values(?,?,?)");

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));


while(true){

System.out.println("enter id");
String s1=br.readLine();
int id=Integer.parseInt(s1);

System.out.println("enter name");
String name=br.readLine();

System.out.println("enter salary");
String s3=br.readLine();
int salary=Integer.parseInt(s3);

ps.setInt(1,id);
ps.setString(2,name);
ps.setInt(3,salary);
ps.executeUpdate();

System.out.println("commit/rollback");
String answer=br.readLine();
if(answer.equals("commit")){
con.commit();
}
if(answer.equals("rollback")){
con.rollback();
}

Lotfi ELAACHAK Page 54


System.out.println("Want to add more records y/n");
String ans=br.readLine();
if(ans.equals("n")){
break;
}

}
con.commit();
System.out.println("record successfully saved");

con.close();//before closing connection commit() is called


}catch(Exception e){System.out.println(e);}

}}

Lotfi ELAACHAK Page 55


6
Chapitre
Les fonctionalités Java 8 , 9 et plus
6.1 Default méthodes sur les Interfaces
Avant Java 8, les interfaces ne pouvaient avoir que des méthodes abstraites. L’implémentation de
ces méthodes doit être fournie dans une classe séparée. Ainsi, si une nouvelle méthode doit être
ajoutée à une interface, son code d’implémentation doit être fourni dans la classe implémentant
la même interface. Pour résoudre ce problème, Java 8 a introduit le concept de méthodes par
défaut qui permet aux interfaces d’avoir des méthodes avec une implémentation sans affecter les
classes qui implémentent l’interface.

Java 8 utilise le mot clef default pour définir une implémentation par défaut au sein d’une in-
terface. C’est utile pour les développeurs d’API, c’était même indispensable pour la plupart des
nouveautés du langage sinon comment enrichir les interfaces comme java.util.Collection.

Default method Interface


// A simple program to Test Interface default
// methods in java
interface TestInterface
{
// abstract method
public void square(int a);

// default method
default void show()
{
System.out.println("Default Method Executed");
}
}

class TestClass implements TestInterface


{
// implementation of square abstract method
public void square(int a)
{
System.out.println(a*a);
}

public static void main(String args[])


{
TestClass d = new TestClass();
d.square(4);

56
// default method executed
d.show();
}
}

Les méthodes par défaut ont été introduites pour assurer une compatibilité ascendante afin que
les interfaces existantes puissent utiliser les expressions lambda sans implémenter les méthodes
dans la classe d’implémentation. Les méthodes par défaut sont également appelées méthodes de
défense ou méthodes d’extension virtuelle.

6.1.1 Static Methods


Les interfaces peuvent également avoir des méthodes statiques, ce qui est similaire aux méthodes
statiques des classes.
Static method Interface
// A simple Java program to TestClassnstrate static
// methods in java
interface TestInterface
{
// abstract method
public void square (int a);

// static method
static void show()
{
System.out.println("Static Method Executed");
}
}

class TestClass implements TestInterface


{
// Implementation of square abstract method
public void square (int a)
{
System.out.println(a*a);
}

public static void main(String args[])


{
TestClass d = new TestClass();
d.square(4);

// Static method executed


TestInterface.show();
}
}

Lotfi ELAACHAK Page 57


6.1.2 Default Methods et Héritage multiple

Default method Interface Héritage multiple


// A simple Java program to demonstrate multiple
// inheritance through default methods.
interface TestInterface1
{
// default method
default void show()
{
System.out.println("Default TestInterface1");
}
}

interface TestInterface2
{
// Default method
default void show()
{
System.out.println("Default TestInterface2");
}
}

// Implementation class code


class TestClass implements TestInterface1, TestInterface2
{
// Overriding default show method
public void show()
{
// use super keyword to call the show
// method of TestInterface1 interface
TestInterface1.super.show();

// use super keyword to call the show


// method of TestInterface2 interface
TestInterface2.super.show();
}

public static void main(String args[])


{
TestClass d = new TestClass();
d.show();
}
}

Lotfi ELAACHAK Page 58


6.2 Expressions Lambda
Surement une des évolutions les plus attendues, une expression lambda est une sorte de méthode
“anonyme”. Jusqu’à aujourd’hui en Java pour simuler ce comportement on utilisait une classe
anonyme qui implémentait une interface avec une seule méthode abstraite.
Java 8 propose les expressions lambda. Les expressions lambda sont aussi nommées closures ou
fonctions anonymes : leur but principal est de permettre de passer en paramètre un ensemble de
traitements.
Dans ce mode de programmation, le résultat de traitements est décrit mais pas la façon dont
ils sont réalisés. Ceci permet de réduire la quantité de code à écrire pour obtenir le même résultat.

Syntaxe des expressions lambda :

lambda operator -> body

Il existe trois paramètres d’expression lambda, mentionnés ci-dessous :

1. Expression lambda avec paramètre zéro : () -> System.out.println("Paramètre zéro de l’ex-


pression lambda")
2. Expression lambda avec un seul paramètre : (p) -> System.out.println("Un paramètre : " + p)
3. Expression lambda avec plusieurs paramètres : (p1, p2) -> System.out.println("Paramètres
multiples : " + p1 + ", " + p2) ;

Lambda Expression
// A Java program to demonstrate simple lambda expressions
import java.util.ArrayList;
class Test {
public static void main(String args[])
{
// Creating an ArrayList with elements
// {1, 2, 3, 4}
ArrayList<Integer> arrL = new ArrayList<Integer>();
arrL.add(1);
arrL.add(2);
arrL.add(3);
arrL.add(4);

// Using lambda expression to print all elements


// of arrL
arrL.forEach(n -> System.out.println(n));

// Using lambda expression to print even elements


// of arrL
arrL.forEach(n -> {
if (n % 2 == 0)
System.out.println(n);
});

Lotfi ELAACHAK Page 59


}
}

Lambda Expression
// Java program to demonstrate working of lambda expressions
public class Test {
// operation is implemented using lambda expressions
interface FuncInter1 {
int operation(int a, int b);
}

// sayMessage() is implemented using lambda expressions


// above
interface FuncInter2 {
void sayMessage(String message);
}

// Performs FuncInter1's operation on 'a' and 'b'


private int operate(int a, int b, FuncInter1 fobj)
{
return fobj.operation(a, b);
}

public static void main(String args[])


{
// lambda expression for addition for two parameters
// data type for x and y is optional.
// This expression implements 'FuncInter1' interface
FuncInter1 add = (int x, int y) -> x + y;

// lambda expression multiplication for two


// parameters This expression also implements
// 'FuncInter1' interface
FuncInter1 multiply = (int x, int y) -> x * y;

// Creating an object of Test to call operate using


// different implementations using lambda
// Expressions
Test tobj = new Test();

// Add two numbers using lambda expression


System.out.println("Addition is "
+ tobj.operate(6, 3, add));

// Multiply two numbers using lambda expression


System.out.println("Multiplication is "

Lotfi ELAACHAK Page 60


+ tobj.operate(6, 3, multiply));

// lambda expression for single parameter


// This expression implements 'FuncInter2' interface
FuncInter2 fobj = message
-> System.out.println("Hello " + message);
fobj.sayMessage("Geek");
}
}

6.3 API Stream


Introduite dans Java 8, l’API Stream est utilisée pour traiter des collections d’objets. En Java,
un flux est une séquence d’objets qui prend en charge diverses méthodes pouvant être combinées
pour produire le résultat souhaité.

Les utilisations de Stream en Java sont mentionnées ci-dessous :


— L’API Stream est un moyen d’exprimer et de traiter des collections d’objets.
— Elle permet d’effectuer des opérations telles que le filtrage, le mappage, la réduction et le
tri.
Comment créer un flux Java ?
La création d’un flux Java est l’une des étapes les plus fondamentales avant d’envisager les
fonctionnalités du flux Java. La syntaxe ci-dessous indique comment déclarer un flux Java.
Syntaxe :
Stream<T> stream ;
Caractéristiques du flux Java Les caractéristiques des flux Java sont mentionnées ci-dessous :
— Un flux n’est pas une structure de données, mais il prend en entrée des collections, des
tableaux ou des canaux d’E/S.
— Les flux ne modifient pas la structure de données d’origine.
— Les flux ne modifient pas la structure de données d’origine, ils fournissent uniquement le
résultat conformément aux méthodes en pipeline.
— Chaque opération intermédiaire est exécutée paresseusement et renvoie un flux comme
résultat, ce qui permet d’enchaîner plusieurs opérations intermédiaires. Les opérations
terminales marquent la fin
Différentes opérations sur les stream Il existe deux types d’opérations dans les stream :
— Les opérations intermédiaires
— Les Opérations de fin

Lotfi ELAACHAK Page 61


Les opérations intermédiaires sont les types d’opérations dans lesquelles plusieurs méthodes sont
enchaînées.
— Caractéristiques des opérations intermédiaires
— Les méthodes sont enchaînées.
— Les opérations intermédiaires transforment un flux en un autre flux.
— Elles permettent le concept de filtrage où une méthode filtre les données et les transmet
à une autre méthode après traitement.

6.3.1 Opérations intermédiaires : map


La méthode map est utilisée pour renvoyer un flux constitué des résultats de l’application de la
fonction donnée aux éléments de ce flux.

List number = Arrays.asList(2,3,4,5) ;


List square = number.stream().map(x->x*x).collect(Collectors.toList()) ;

6.3.2 Opérations intermédiaires : filter


La méthode filter est utilisée pour sélectionner des éléments en fonction du prédicat transmis en
tant qu’argument.

List names = Arrays.asList("Reflection","Collection","Stream") ;


List result = names.stream().filter(s->s.startsWith("S")).collect(Collectors.toList()) ;

6.3.3 Opérations intermédiaires : sorted


La méthode sorted est utilisée pour trier le flux.

Liste names = Arrays.asList("Reflection", "Collection", "Stream") ;


Liste result = names.stream().sorted().collect(Collectors.toList()) ;

6.3.4 Opérations terminaux : collect


La méthode collect est utilisée pour renvoyer le résultat des opérations intermédiaires effectuées
sur le flux.

Lotfi ELAACHAK Page 62


Liste number = Arrays.asList(2,3,4,5,3) ;
Set square = number.stream().map(x->x*x).collect(Collectors.toSet()) ;

6.3.5 Opérations terminaux : forEach


La méthode forEach est utilisée pour parcourir chaque élément du flux.

Liste nombre = Arrays.asList(2,3,4,5) ;


number.stream().map(x->x*x).forEach(y->System.out.println(y)) ;

6.3.6 Opérations terminaux : reduce


La méthode reduce est utilisée pour réduire les éléments d’un flux en une seule valeur. La méthode
reduce prend un BinaryOperator en paramètre.

Liste number = Arrays.asList(2,3,4,5) ;


int even = number.stream().filter(x->x%2==0).reduce(0,(ans,i)-> ans+i) ;

Java Stream
// Java program to demonstrate
// the use of stream in java
import java.util.*;
import java.util.stream.*;

class Demo {
public static void main(String args[])
{
// create a list of integers
List<Integer> number = Arrays.asList(2, 3, 4, 5);

// demonstration of map method


List<Integer> square
= number.stream()
.map(x -> x * x)
.collect(Collectors.toList());

// create a list of String


List<String> names = Arrays.asList(
"Reflection", "Collection", "Stream");

// demonstration of filter method


List<String> result
= names.stream()
.filter(s -> s.startsWith("S"))
.collect(Collectors.toList());

Lotfi ELAACHAK Page 63


System.out.println(result);

// demonstration of sorted method


List<String> show
= names.stream()
.sorted()
.collect(Collectors.toList());

System.out.println(show);

// create a list of integers


List<Integer> numbers
= Arrays.asList(2, 3, 4, 5, 2);

// collect method returns a set


Set<Integer> squareSet
= numbers.stream()
.map(x -> x * x)
.collect(Collectors.toSet());

System.out.println(squareSet);

// demonstration of forEach method


number.stream()
.map(x -> x * x)
.forEach(y -> System.out.println(y));

// demonstration of reduce method


int even
= number.stream()
.filter(x -> x % 2 == 0)
.reduce(0, (ans, i) -> ans + i);

System.out.println(even);
}
}

Lotfi ELAACHAK Page 64

Vous aimerez peut-être aussi