Typage de données
class NomDuType {
/* Corps de la classe: instructions de définitions
des méthodes et des champs */
}
class UnTest {
float x;
int i;
boolean b;
}
ENSAM 2020-2021- T.HAJJI- 18
Définition des méthodes
La définition de base d’une méthode ressemble à la définition
d’une fonction en C.
typeRetour nomMethode (/* Liste des parametres */) {
/* corps de la méthode */
}
- nomMethode est le nom de la méthode
- Liste de paramètre (arguments de la méthode) donne les
types et les noms des informations qu’on souhaite passer à
la méthode lors de son appel.
- typeRetour est le type de la valeur qui est retournée par la
méthode après son appel. Si la méthode ne fourni aucun
résultat, alors typeRetour est remplacé par le mot clé void.
Exemple
class C {
void methode1(int i){
i+=12;
}
void methode2() {
int i = 3;
methode1(i);
System.out.println(i=" + i); // i=3
}
}
ENSAM 2020-2021- T.HAJJI- 20
IV. Création et manipulation d’Objets
Une fois la classe est définie, on peut créer des objets de la même
manière que la déclaration des types primitif:
class ClasseTest {
// corps de la classe ClasseTest
}
l’instruction:
Objet
Référence
Télécommande Télé
class NomClasse {
/* Corps de la classe */
}
En générale:
1. Chaque objet met ses données membres dans sa propre zone
mémoire.
2. Les données membres ne sont partagées entre les objets.
ENSAM 2020-2021- T.HAJJI- 24
Exemple 1:
class UnTest {
float x;
int i;
boolean b;
}
class UnTest {
float x;
int i;
boolean b;
int f() {
return 10;
}
}
------------------------------------------------------------------------------
Type | Taille | Classe Wrapper |
--------- |--------------------------------|--------------------------------- |
boolean | | Boolean |
char | 16 bits, Unicode | Character |
byte | 8 bits | Byte |
short | 16 bits | Short |
int | 32 bits | Integer |
long | 64 bits | Long |
float | 32 bits IEEE 754 | Float |
double | 64 bits IEEE 754 | Double |
void | | Void |
Exemple:
char c=‘x’; // type primitif directement déclaré
Character car = new Character(c); // classe wrapper
ou
Character car = new Character (‘x’);
{
A a=new A();
} // fin de portée
Remarque:
- Tous les caractères sont significatifs.
- On fait la différence entre les majuscules et les minuscules.
- Mots clés: certains mots sont réservés par le langage et ne
peuvent pas être utilisés comme identificateur.
I. Introduction
Un objet a
– une adresse en mémoire (identifie l’objet)
– un comportement (ou interface)
– un état interne (les valeurs des variables)
De manière générale on a:
objetQuiReçoitLeMessage.messageEnvoyé(paramètres);
a.initialise(1,1);
a.deplace(0,2);
Exemple:
Prenons l’exemple de la classe point et transformons la
méthode initialise en un constructeur en la nommant Point.
Attention.
Dans la dernière version de la définition de la classe Point, l’instruction
Point a = new Point();
ne convient plus car le constructeur a besoin de deux arguments
A a=new A();
Cela signifie que:
- Soit A ne possède pas de constructeur
- Soit A possède un constructeur sans arguments.
class A{
public A (…) {… } // Constructeur A
…
private int n=10;
private int p;
}
Entraîne successivement
- l’initialisation implicite des champs n et p de l’objet objA à 0
- L’initialisation (explicite) du champ n à la valeur figurant
dans sa déclaration, soit 10
- L’exécution des instruction du constructeur
class Etudiant {
private String nom, prenom; // Variables d’instance
private int codeNatEtudiant;
public Etudiant(String n, String p) { // Constructeur
nom = n;
prenom = p;
}
public Etudiant(String n, String p, int cne) {// Constructeur
nom = n;
prenom = p;
codeNatEtudiant = cne;
}
}
class A {
….
public void f(….) {
…… // ici l’emploi de this désigne la référence à l’objet
// ayant appelé la méthode f
}
}
class Etudiant {
private String nom, prenom;
public Etudiant(String nom, String prenom) {
this.nom = nom;
this.prenom = prenom;
}
class Point {
public Point (int abs, int ord){
x=abs; y=ord;
}
public Point( ) {
this (0,0);
}
…
private int x,y;
}
Point a = new Point (); // créer l’objet a et l’initialise à l’origine,
// au point (0,0).
Point b = new Point (2,3); // créer l’objet b et l’initialise au point (2,3).
ENSAM 2020-2021- T.HAJJI- 84
public class feuille {
int i=0;
feuille increment () {
i++;
return this;
}
public static void main (String[] args ) {
feuille x=new feuille ();
System.out.println("ii = " + x.increment().increment().increment().i );
}
}
Sortie:
i= 3
Sortie:
i= 3
Types de variables
• Les variables d’instances
– sont déclarées en dehors de toute méthode
– conservent l’état d’un objet, instance de la classe
– sont accessibles et partagées par toutes les méthodes de la classe
• Les variables locales
– sont déclarées à l’intérieur d’une méthode
– conservent une valeur utilisée pendant l’exécution de la méthode
– ne sont accessibles que dans le bloc dans lequel elles ont été
déclarées
Exemple:
.567e2 // 5,67 de type double
5.123E-2F // 0,05123 type float
int x = y + 5;
if (x % 2 == 0) {
type = 0;
x++;
}
else
type = 1;
Exemple:
int y = (x % 2 == 0) ? x + 1 : x;
est équivalent à
int y;
if (x % 2 == 0)
y = x + 1;
else
y = x;
Parenthèses pas indispensables
switch(expression) {
case val1: instructions;
break; // Attention, sans break, les instructions du cas suivant
// sont exécutées !
...
case valn: instructions;
break;
default: instructions;
}
expression est de type char, byte, short, ou int, ou de type énumération
• S’il n’y a pas de clause default, rien n’est exécuté si expression ne
correspond à aucun case
while(expressionBooléenne)
bloc-instructions ou instruction
do bloc-instructions ou instruction
while(expressionBooléenne)
int somme = 0;
for (int i=0; i < n; i++) {
somme += tab[i];
}
System.out.println(somme);
Taille du tableau
int[] tab = {10, 3*6, 4};
tabNotes = new int[8];
int l1 = tab.length; // l1 = 3
int l2 = tabNots.length; // l2 = 8
int e = tabNotes[8];
/* La compilation produit le message suivant :
ArrayIndexOutOfBoundsException */
class TestArguments {
public static void main(String[] args) {
for (int i=0; i < args.length; i++)
System.out.println(args[i]);
}
}
$javac TestArguments
$ java TestArguments arg1 arg2
affichera
• arg1
• arg2
etudianSMI[0].codeNatEtudiant = cne;
// Erreur: etudiantSMI[0] est objet de type Etudiant, donc il faut le créer avant de l’utiliser
• Déclaration
Sortie:
Classe de Base : 14
Classe dérivée1: 7 , 7
Classe dérivée2: 7
Sortie:
Classe de Base :
Classe dérivée1:
Classe dérivée2:
Class A: méthode de A
B Classe B: méthode de A
C* Classe D: méthode de D
Classe E: méthode de A
Classe C: méthode de C
Classe F: méthode de C
E
D* F
class A {
public void f(){
System.out.println("Methode f(): Classe de base A");
}
public void g(){
System.out.println("Methode g(): Classe de base A");
}
}
class B extends A {
public void f(){
System.out.println("Methode f(): Classe B derivee de A");
public void h(){
System.out.println("Methode h(): Classe B derivee de A");
}
}
Il faut noter que la même écriture a.f(); peut correspondre à des appels
différents de la méthode f(). Ceci est réalisé grâce au polymorphisme.
Soit B une classe qui hérite de la classe A, et soit f() une méthode définie
dans A et redéfinie dans B. Si on a:
A a = new B();
a.f();
Alors la méthode f() appelée est celle définie dans B.
Exemple
Considérons une classe FormeGeometrique. Supposons
que les classes Rectangle et Cercle héritent de la super
classe FormeGeometrique. Dans un tableau hétérogène, on
ranges des objets de type Rectangle, Cercle. Ensuite on
affiche le contenu du tableau
class FormeFigure {
public FormeFigure(int x, int y) { // constructeur
this.x=x; this.y=y;
}
public void dessineFigure() {
afficheMonIdentite();
System.out.println(" ma position dans le plan est (" + x + " ," + y + ")" );
}
public void afficheMonIdentite(){}; // méthode vide
private int x,y;
}
• Exemple :
FormeFigure a = new FormeFigure();
Rectangle r = (Rectangle) a;
FormeFigure b;
(Rectangle) b = r;
Les appels de Point(6,1) et deplace(-1, 2) n’ont pas généré d’exception, donc ils sont
exécutés normalement. Par contre l’appel de Point(-2,4) a généré une exception et
a provoqué l’arrêt du programme (appel de System.exit(-1);). L’appel de
deplace(3,-6) et l’instruction System.out.printl() n’ont pas été exécutés.
try {
/* code */
}
La gestion des exceptions est obtenue par des blocs catch, où un bloc catch est associé à
une exception donnée.
Attention: Le bloc catch doit être juste après le bloc try, sinon erreur de compilation.
catch ( Type1Exception e) { // de type Type1Exception qui hérite de Exception
/* code */
}
catch ( Type2Exception e) { // de type Type2Exception qui hérite de Exception
/* code */
}
…..
L’appel de Point(-2,4); génère une exception, donc un saut est effectué vers le bloc catch().
L’exécution du code du bloc catch() a provoqué l’arrêt du programme (appel de System.exit(-1);),
par conséquent l’appel de deplace(3,-6) et les instructions a près le bloc try n’ont pas été exécutés.
L’appel de Point(6,1) et Point(2,4) n’ont pas généré d’exception donc le code catch()
n’a pas été exécuté par conséquent l’exécution est allée au-delà du bloc try.
L’appel de deplace(-3,1) a généré une exception, donc un saut est effectué vers le bloc
catch(ErrDepl). L’exécution du code du bloc catch(ErrDepl) a provoqué l’arrêt du programme
(appel de System.exit(-1);).
Throwable
Error
Exception
Sortie:
Erreur au point x= -2 et y=4
Sortie:
Erreur aux points -2 et 4
Erreur de Construction
ErrConst
at Point.<init>(ExceptionTestStack.java:5)
at ExceptionTestStack.main(ExceptionTestStack.java:14)
class A {
…
private float x; // champs usuel
static int n; // champs de classe
public static void f() { // méthode de clase
… //ici, on ne pas accéder au champs x, champs usuel
… // ici on peut accéder au champs n
}
}
}
public class MethodeStatic{
public static void main(String[] argv) {
Etudiant e= new Etudiant("Mohammed","Ali");
// comment afficher le nom de l’etudiant e; ??
// System.out.println("Nom = "+e.nom); ne marche pas car nom est privé
}
}
Exemple 1:
class ClasseTest {
public ClasseTest() {
System.out.println(" Ceci est un exemple : ");
}
}
public class TestPackage {
public static void main(String[] args) {
System.out.print("Entrer un entier nouvelle largeur : ");
int i = Clavier.lireInt();
}
}
Attention:
L'instruction import java.awt.*; ne permet pas d’importer les
classes des sous-paquetages de java.awt
Si on veut par exemple importer les classes de java.awt et aussi
celles de java.awt.event alors on devra écrire:
import java.awt.*;
import java.awt.event.*;
}
private JButton monBouton;
}
Exemple
– L’événement émis suite à un clic souris dans une fenêtre est
de type MouseEvent
– L’événement émis suite à un clic souris sur un bouton est de
type ActionEvent
if (ev.getSource()==monBoutonA)
System.out.println("Action sur un BoutonA");
if (ev.getSource()==monBoutonB)
System.out.println("Action sur un BoutonB");
}
private JButton monBoutonA, monBoutonB;
}
Exemple
import java.awt.* ; import java.awt.event.* ;
import javax.swing.* ; import javax.swing.event.* ;
class MaFenetre extends JFrame {
private JCheckBox MaCase;
public MaFenetre () {
super("Une fenetre avec une case") ;
setBounds(10,40,300,200) ;
MaCase = new JCheckBox("Une case") ;
// création d’une case à cocher de référence MaCase portant l’étiquette Une case
getContentPane().add(MaCase) ;
}
}
• Tableaux,
• Collection,
• Map
• Vues et ponts entre les structures Itération
• Legacy
Les Collections
● Structure modifiable, différents algorithmes de stockage
Les Map
● Structure modifiable, stocke des couples clé -> valeur
list.add("hello"); // ok
list2.size(); // renvoie 1
Cela permet d'éviter les copie défensive !
ENSAM 2020-2021- T.HAJJI- 291
Object ou E ?
Pourquoi remove(Object) et add(E) ?
A cause des interfaces interface I {}
interface J {}
class A implements I, J {}
public static void main(String[] args) {
Collection<I> collection = ...
A a = new A();
collection.add(a);// ok, A est un sous-type de I J
j = a;
collection.remove(j); // doit être valide
}
ENSAM 2020-2021- T.HAJJI- 292
Recherche
java.util.Collection possède une méthode de recherche
boolean contains(Object)
Renvoie vrai si l'objet est stocké dans la collection
Note sur la complexité:
contains (ou add, remove, etc.) a une complexité différente suivant
la structure de donnée
contains pour une HashSet est O(1), pour un TreeSet est O(ln n) et pour une
ArrayList O(n)
Méthodes supplémentaires
E get(int index), E set(int index, E element)
accès
● en utilisant un index
int indexOf(E element), lastIndexOf(E element)
comme
● contains mais qui renvoie un index ou -1
void sort(Comparator<? Super E>)
Trie
● en fonction d'un ordre de comparaison
LinkedList
List doublement chaînée
Ajout à la fin en 0(1), ajout au début en O(1), accès indexé en O(n)
Méthodes supplémentaires
boolean offer(E)
ajoute à la fin, renvoie vrai si ajouté
E poll()
retire en tête, null si vide
E peek()
regarde l'élement en tête sans le retirer, null si vide
ENSAM 2020-2021- T.HAJJI- 308
Implantations de Queue
ArrayDeque
Tableau dynamique circulaire
Ajout/suppression en O(1)
PriorityQueue
Tas (ordre de comparaison)
Ajout/suppression en O(ln n)
LinkedList
Liste double chainée
Ajout/suppression en O(1)
ENSAM 2020-2021- T.HAJJI- 309
Autre sémantique
En plus de offer/poll/peek, il existe 3 autres méthodes
qui ont la même sémantique mais plante au lieu de
renvoyer null/false, elles sont peu utilisées en pratique
V remove(Object key)
boolean remove(Object key, Object value)
supprime un couple (à partir de la clé, ou du couple)
Opérations
K getKey()
renvoie la clé du couple
V getValue()
renvoie la valeur du couple
V setValue(V value)
change la valeur du couple (opération mutable optionelle)
AbstractMap.SimpleImmutableEntry<K,V>
version non mutable, setValue jète une UOE
AbstractMap.SimpleEntry<K,V>
version mutable, equals/hashCode/toString passe par les getters et donc ils
peuvent être redéfinie
exemple :
Map<String, Option> map = ... map.forEach((key, value) -> {
System.out.println("key: " + key + " value: " + value);
});
Itérateur au début
e1 e2 e3 e4 e5 e6
–AbstractSet
–AbstractQueue
–AbstractMap
–AbstractList / AbstractSequentialList
Pour les listes AbstractSequentialList hérite de AbstractList ce qui est une
erreur de design !
public static <T,U> List<U> map(List<T> list, Function<? super T, ? extends U> mapper) {
class MappedList extends List<U> implements RandomAccess {
@Override
public int size() {
return list.size();
}
@Override
public U get(int index) {
return mapper.apply(list.get(index));
}
}
return new MappedList();
}
Complexité
–Insertion/suppression au début/à la fin en 0(1) amortie
Parcours:
–Avec un itérateur O(n)
–Utiliseun seul tableau avec les clés et les valeurs à des index
consécutif
Liés a Java :
• Portabilité sur de nombreux O.S. et sur de
nombreuses SGBDR (Oracle, Informix,
Sybase, ..)
• Uniformité du langage de description des
applications, des applets et des accès aux bases
de données
• Liberté totale vis a vis des constructeurs
378
379
– Le driver JDBC
• Fourni par le fournisseur de la base ou autre
• Adapté à la BD
• Convertit les requêtes JDBC en requêtes propres à la base
380
381
382
386
387
389
391
• Scénario 1 :
– architecture 2-tiers avec une application Java
392
• Scénario 2 :
– architecture 2-tiers avec une applet Java
393
• Scénario 3 :
– architecture 3-tiers et applet/application Java
394
Classe Role
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch(ClassNotFoundException e) {
System.err.println("Erreur de chargement du driver :" + e);
}
400
Exemple:
String url=jdbc:odbc:Mabase
Import java.sql.* ;
...
try {
Connection con = DriverManager.getConnection(url,userId,password) ;
}
catch(SQLException sqle) {
System.err.println("Erreur lors de la connexion : " + sqle) ;
}
402
403
404
• 3 types de Statement :
ENSAM 2020-2021- T.HAJJI- 404
– Statement : requêtes statiques simples
Exécution d’une requête
while(resultset.next()) {
System.out.println(resultset.getString(1)) ;
} 406
getDate(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme
de date.
getDate(String)
next() se déplace sur le prochain enregistrement : retourne false si la fin est atteinte
Close() ferme le ResultSet
407
getMetaData() retourne un objet ResultSetMetaData associé au ResultSet.
408
import java.sql.*;
import java.io.*;
public class SuppressionBaseDeDonnees {
public static void main(String args[]) {
DataInputStream din = new DataInputStream(System.in);
String url = "jdbc:odbc:BDMUS",N;
PreparedStatement req=null;
Connection con=null;
try { con = DriverManager.getConnection (url);}
catch (Exception e) { System.err.println("Erreur de connexion à jdbc:odbc:BDID");}
try {
System.out.print("\nNom : ");
N = din.readLine();
req=con.prepareStatement("delete from identite where Nom='"+N+"'");
req.executeUpdate();
}
catch (Exception e) { e.printStackTrace(); }
finally { try {con.close();}
catch(SQLException e) {e.printStackTrace();}
}
} //Fin de la methode main
}//Fin du programme
411
import java.sql.*;
public class Connexion {
private Connection connexion;
private Statement instruction;
protected ResultSet résultat;
String DB="mabase";
public Connexion() { //constructeur
try {
Class.forName("com.mysql.jdbc.Driver");
connexion = DriverManager.getConnection("jdbc:mysql://localhost:3333/mabase",
"root", "");
instruction = connexion.createStatement();
}
catch (ClassNotFoundException ex) {
System.err.println("Problème de pilote");
}
catch (SQLException ex) {
System.err.println("Base de données non trouvée ou requête incorrecte");
}
}
public void lire(String requête) { //--- }
public void miseAJour(String requête) { //--- }
public boolean suivant() { //--- }
} 412
}
public ListePersonne() {
lire("SELECT * FROM personne");
}
public String nom() {
try {
return résultat.getString("nom");
} catch (SQLException ex) {
return "";
}
}
public String prenom() { //-- }
}
LP.arrêt();
}
}
ListePersonne
public ListePersonne()
public ListePersonne(int id)
public String nom()
public String prenom() 414
public String email()
public int id()
ENSAM 2020-2021- T.HAJJI- 414
PreparedStatement
415
PreparedStatement pSmt =
conX.prepareStatement("SELECT * FROM Livres" );
ResultSet rs = pSmt.executeQuery();
Exemple :
418
419
boolean absolute() déplace le curseur sur la ligne dont le numéro est fournie en paramètre à partir
du début si il est positif et à partir de la fin si il est négatif. 1 déplace sur la
première ligne, 1 sur la dernière, -2 sur l'avant dernière ...
boolean relative(int) déplace le curseur du nombre de lignes fourni en paramètre par rapport à la
position courante du curseur. Le paramètre doit être négatif pour se déplacer
vers le début et positif pur se déplacer vers la fin. Avant l'appel de cette
méthode, il faut obligatoirement que le curseur soit positionné sur une ligne.
boolean previous() déplace le curseur sur la ligne précédente. Le booleen indique si la première
occurrence est dépassée.
421
void afterLast()
déplace le curseur après la dernière ligne
void beforeFirst()
déplace le curseur avant la première ligne
int getRow()
renvoie le numéro de la ligne courante
422
inserRow()
ENSAM 2020-2021- T.HAJJI- 423
permet de valider la création de la ligne
Accès aux méta-données
La méthode getMetaData () permet d’obtenir
des informations sur les types de données du
ResultSet
elle renvoie des ResultSetMetaData
on peut connaître entre autres :
le nombre de colonne : getColumnCount()
le nom d’une colonne : getColumnName(int
col)
le nom de la table : getTableName(int col)
si un NULL SQL peut être stocké dans une colonne :
isNullable() 424
425
428
429
Les threads
• Distinguer la méthode run (qui est le code exécuté par l’activité) et la méthode
start (méthode de la classe Thread qui rend l’activité exécutable) ;
• Dans la première méthode de création, attention à définir la méthode run avec
strictement le prototype indiqué (il faut redéfinir Thread.run et non pas la
surcharger).
• Créé :
- comme n’importe quel objet Java
- ... mais n’est pas encore actif
- Actif :
- après la création, il est activé par start() qui lance run().
- il est alors ajouté dans la liste des threads actifs pour être exécuté
par l’OS en temps partagé
- peut revenir dans cet état après un resume() ou un notify()
• Endormi ou bloqué :
– après sleep() : endormi pendant un intervalle de temps (ms)
– suspend() endort le Thread mais resume() le réactive
– une entrée/sortie bloquante (ouverture de fichier, entrée clavier)
endort et réveille un Thread
• Mort :
– si stop() est appelé explicitement
– quand run() a terminé son exécution
• Principes :
– Java permet de modifier les priorités (niveaux absolus) desThreads par la
méthode setPriority()
– Par défaut, chaque nouveau Thread a la même priorité que le Thread qui l’a
crée
– Rappel : seuls les Threads actifs peuvent être exécutés et donc accéder au
CPU
– La JVM choisit d’exécuter le Thread actif qui a la plus haute priorité :
priority-based scheduling
– si plusieurs Threads ont la même priorité, la JVM répartit équitablement le
temps CPU (time slicing) entre tous : round-robin scheduling
• Les méthodes :
– setPriority(int) : fixe la priorité du receveur.
• le paramètre doit appartenir à :
[MIN_PRIORITY, MAX_PRIORITY]
• sinon IllegalArgumentException est levée
– int getPriority() : pour connaître la priorité d’un Thread
NORM_PRIORITY : donne le niveau de priorité
"normal"
HAJJI TARIK
Docteur en Informatique