Académique Documents
Professionnel Documents
Culture Documents
Etienne Duris
Bibliographie et sources
Le cours de Marie-Pierre Bal http://igm.univ-mlv.fr/~beal/ Les cours de Rmi Forax http://igm.univ-mlv.fr/~forax/ Java et Internet G. Roussel, E. Duris, N. Bedon et R. Forax. Vuibert 2002. Documentations Java Oracle http://docs.oracle.com/javase/ The Java Language Specification, Third Edition: http://java.sun.com/docs/books/jls/ The Java Virtual Machine Specification, Second Ed: http://java.sun.docs/books/jvms
Style applicatif
Fond sur l'valuation d'expressions qui ne dpendent que de la valeur des arguments, et non de l'tat de la mmoire
On parle aussi de programmation fonctionnelle Proche des notations mathmatiques, utilise beaucoup la rcursivit Accepte des arguments, produit un rsultat (pas d' effet de bord ) Ex: Lisp, Caml, ML, Haskel
Style impratif
Utilise beaucoup les itrations et autres structures de contrle Les structures de donnes sont fondamentales Ex: Fortran, C, Pascal
3 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Le style objet
C'est un style de programmation o l'on considre que des composants autonomes (les objets) disposent de ressources et de moyens d'interactions entre-eux. Ces objets reprsentent des donnes qui sont modlises par des classes qui dfinissent des types
En plus de la manire dont sont structurs leurs objets, les classes dfinissent les actions qu'ils peuvent prendre en charge et la manire dont ces actions affectent leur tat
Les caractristiques de bases prcdemment dcrites peuvent tre mises en oeuvre dans un style impratif, mais des fonctionnalits propres au style objet favorisent:
facile dvelopper, maintenir, faire voluer, rutilisable, tout ou en partie, sans avoir besoin de le dupliquer gnrique, et dont les spcialisations sont transparentes
Programmation modulaire
La conception par classes, reprsentant la fois les donnes, les actions et les responsabilits des objets de cette classe, permet de bien distinguer et sparer les concepts Le fait de dfinir des interfaces , au sens moyens et modalits de communication avec l'extrieur permet de cacher les dtails d'implmentation et d'viter les dpendances trop fortes Tout a favorise la rutilisabilit et la composition / dlgation: l'assemblage des composants en respectant leurs responsabilits
6 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
L'abstraction et la spcialisation
L'abstraction demande sparer la dfinition (d'un type, d'une classe, d'une mthode) de l'implmentation
Permet d'identifier un modle commun plusieurs composants Ce modle commun pourra tre partag via le mcanisme d'hritage
La spcialisation traite des cas particuliers, mais elle doit autant que possible rester transparente:
Le langage Java:
Toute variable doit tre dclare avec un type Le compilateur vrifie que les utilisations des variables sont compatibles avec leur type (notamment via un sous-typage correct) Les types sont d'une part fournis par le langage, mais galement par la dfinition des classes En bytecode, i.e., code intermdiaire indpendant de la machine Le bytecode est interpt par une machine virtuelle Java
est compil
est interprt
Premier exemple
Rgle: toute classe publique doit tre dans un fichier qui a le mme nom que la classe Rgle: tout code doit tre l'intrieur d'une classe
public class HelloWorld { /* Un style de commentaire sur plusieurs lignes. */ public static void main(String[] args) { // Un commentaire sur une seule ligne System.out.println("Bon our ! "ous les #$%&")' ( (
a dfinit une classe, qui est une unit de compilation Comme il y a une mthode main, cette classe est excutable
9 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Fichier HelloWorld.java
public class HelloWorld { /* Un style de commentaire sur plusieurs lignes. */ public static void main(String[] args) { // Un commentaire sur une seule ligne System.out.println("Bonjour vous les IR1!"); } }
Linux Java Virtual Machine java HelloWorld Interprtation / excution (write once, run everywhere) Bonjour vous les IR1! Pile Tas
Compiled from "HelloWorld.java" public class HelloWorld extends java.lang.Object{ public HelloWorld(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Bonjour vous les IR1! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
Le bytecode
Le langage source Java est dfini par la JLS (Java Language Specification) dite par Sun-Oracle
Le code source d'une classe contenue dans un fichier est compil avec la commande javac
Cela produit un code intermdiaire, appel bytecode, qui est le langage machine de la machine virtuelle Java
Le bytecode d'une classe est destin tre charg par une machine virtuelle qui doit l'excuter avec la comande java
Soit par interprtation, soit par compilation juste temps (just-in-time ou JIT) L'argument est le nom de la classe (sans l'extension .class)
11 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Pour le rendre le + possible indpendant de la plateforme Son comportement est dfini par la JVM Spec dit par SunOracle (actuellement version 2)
Qui peut tre adapte une plateforme d'accueil (Windows, Linux, Mac...) Qui peut tre dveloppe par Sun (HotSpot: open source GPL depuis 2006) ou par d'autres: IBM, Jikes, etc.
De la JVM et des APIs (Application Programming Interfaces) regroupes dans une plateforme :
Java SE (Java Platform, Standard Edition): Java SE 6 pour applications classiques, desktop Java EE (Java Platform, Enterprise Edition): Java EE 6 pour dvelopper et dployer des applications serveur, Web services, etc. Java ME (Java Platform, Micro Edition): J2ME pour les applications embarques, PDA, tlphones, etc.
Si on veut juste excuter, il suffit du JRE (Java Runtime Execution) par opposition au JDK (Java Developpement Kit)
13 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Le langage Java
Les variables, les oprateurs, les expressions, instructions, blocs, contrle de flot sont trs proches de ceux du C
Les exceptions sont une nouveaut Les types primitifs ont une taille et une reprsentation norme
S'y ajoutent des spcificits syntaxiques lies la programmation objet, aux classes, l'hritage... Un style de nommage (trs fortement) conseill
Style chameau (CamelCase) pour les indentificateurs Premire majuscule pour les classes (class HelloWorld) Premire minuscule pour les variables/champs et les fonctions/mthodes (radius, getRadius()) Tout en majuscule pour les constantes (MAX_SIZE)
15 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Classes et objets
La compilation d'un programme qui contient une classe Toto produira un fichier Toto.class Il peut servir dclarer des variables comme Toto t; Cela ncessite en gnral la dfinition d'un ensemble de champs (fields) dcrivant l'tat d'un objet de ce type et d'un ensemble de mthodes dfinissant son comportement ou ses focntionnalits Dispose de son propre tat (la valeur de ses champs) Rpond au mme comportement (via les mthodes de la classe)
16 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Une classe est dfinie par son nom et son package d'appartenance (ex: java.lang.String)
En l'absence de directive, les classes sont dans un package dit par dfaut (i.e., pas de packge).
Des champs (fields) ou attributs Des mthodes (methods) et constructeurs Des classes internes
Les membres non statiques (ou d'instance) ne peuvent exister sans un objet
public class )i*el { public final static int ORIGIN + ,' private int *' private int y' public )i*el(int *- int y) { Constante this.* + *' this.y + y' ( Champs public void reset() { * + ORIGIN' y + ORIGIN' Constructeur ( public void print.nScreen() { System.out.println("("/*/"-"/y/")")' Mthodes ( d'instances public static boolean same()i*el p%- )i*el p0) { return (p%.*++p0.*) 11 (p%.y++p0.y)' Mthode ( de classe public static void main(String[] args) { )i*el p, + new )i*el(,-,)' Variables locales )i*el p% + new )i*el(%-2)' la mthode p%.print.nScreen()' // (%-2) main et System.out.println(same(p,-p%))' // 3alse objets de la p%.reset()' classe Pixel System.out.println(same(p,-p%))' // true ( 18 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Exemple
Les objets sont manipuls via des rfrences (sortes d'adresses mmoire)
Lorsque la mthode
p%.reset()' Classe Pixel #s ORIGIN = 0
mthodes main
Pixel p1 Pixel p2
#1 #2
#1
@ class Pixel
est excut sur la pile avec les rfrences #1 la place de p1 et #s la place de ORIGIN
public void reset() { 4%.* + #s' 4%.y + #s' (
x=1 y=3 #2
@ class Pixel
0 0
x=0
y=0
19
constructeur
Les variables locales comme les champs des classes et des objets ne peuvent tre que de deux natures De type primitif
Dans ce cas, la dclaration de la variable rserve la place mmoire pour stocker sa valeur (qui dpend de son type)
int entier; long entierLong;
Dans ce cas, la dclaration de la variable ne fait que rserver la place d'une rfrence (une sorte de pointeur) qui permettra d'accder l'endroit en mmoire o est effectivement stock l'objet en lui-mme (vaut null si rfrence inconnue)
Pixel p1; p1=new Pixel(1,3); #1 #1
@ class Pixel
x=1
objet
20
byte (octet) sur 8 bits: [-128 .. 127] short sur 16 bits [-32768 .. 32767] int sur 32 bits [-2147483648 .. 2147483647] (dfaut pour entiers) long sur 64 bits [-9223372036854775808 .. 9223372036854775807]
Type boolen:
21
Pour la plupart des oprations, les valeurs entires sont transforms en des int (promotion entire):
short s = 4; s = s+s; // Type mismatch: cannot convert int to short s = (short) (s+s); // cast ncessaire
Les dbordements ou cas d'erreurs sont prvus pour les flottants (Infinity et Not-a-Number):
Ils ne sont que des approximation des valeurs Leur galit au sens de l'oprateur == n'a aucun sens
double d = 0.0; int nb = 0; double expected = 1.0; while (d != 1.0 /* && nb < 10 */ ! // boucle infinie!!! d "= 0.1; nb""; # $%ste&.out.println('nb( ' " nb " ' d( ' " d ; // $i on d)co&&ente* affiche nb( 10 d( 0.++++++++++++++++
23
Tous les autres types sont objets et sont manipuls via des rfrences
#1
#1
@class String
#2 ... #2 t o t o \n
int[] tab = {3, 5, 7, 9}; String[] args; Pixel[] array = new Pixel[2];
#1 null #2 #2
@class Pixel[]
#1
@class int[]
length = 4 3 5 7 9
24 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Lors des appels de mthode, les arguments sont toujours passs par valeur Dans le cas des types primitifs, c'est la valeur de l'argument qui est recopie dans le paramtre de la mthode
Les modifications sur le paramtre de la mthode sont sans effet sur l'argument
Dans le cas des types objet , c'est la valeur de la variable, (la rfrence l'objet) qui est transmise la mthode
Les modifications effectues en suivant cette rfrence (e.g. modification d'un champ de l'objet) sont rpercuts dans la mmoire et sont donc visibles sur l'argument En revanche, la modification de la rfrence elle-mme est sans effet sur l'argument (c'en est une copie)
25
Dans le cas des types primitifs, c'est la valeur de l'argument qui est recopie dans le paramtre de la mthode
Les modifications sur le paramtre de la mthode sont sans effet sur l'argument
! entier 5
Dans le cas des types objet , c'est la valeur de la variable, (la rfrence l'objet) qui est transmise la mthode
Les modifications effectues en suivant cette rfrence (e.g. modification d'un champ de l'objet) sont rpercuts dans la mmoire et sont donc visibles sur l'argument
#1
@class Box
#1
field = 5
6
box #1 class 4ox ! int field; #
public static void &ain($trin/01 ar/s ! 4ox box = new 4ox( ; box.field = 2; m2(box ; $%ste&.out.println(box.field ; // 5 #
27
Dans le cas des types objet , c'est la valeur de la variable, (la rfrence l'objet) qui est transmise la mthode
En revanche, la modification de la rfrence elle-mme est sans effet sur l'argument (c'en est une copie)
#2
@class Box
tmp public static void &6(4ox b ! 4ox t&p = new 4ox( ; t&p.field = b.field"1; b b = t&p; # public static void &ain($trin/01 ar/s ! 4ox box = new 4ox( ; box box.field = 2; m3(box ; $%ste&.out.println(box.field ; // 2 #
#2 #1
field = 6
#2
#1
@class Box
field = 5
28
Lorsqu'on dclare une variable de type objet, seule la place de la rfrence est rserve sur la pile d'excution (registre)
4 octets, 32 bits, et ce quelque soit le type de l'objet rfrenc Par dfaut, cette rfrence vaut une valeur particulire, null. Il est interdit de tenter d'y accder, de la drfrencer
public static void &ain($trin/01 ar/s ! 4ox b; $%ste&.out.println(b.field ; // 7ariable b &i/ht not have been initiali8ed #
public static void &ain($trin/01 ar/s ! 4ox b = null; $%ste&.out.println(b.field ; // l9ve :ull;ointer<xception
29 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Allocation mmoire
Pour qu'une variable objet prenne une autre valeur que null, il faut tre capable d'y affecter une rfrence
Elle peut tre produite (retourne) par l'oprateur d'allocation new Cet oprateur besoin de connatre la taille de l'objet qu'il doit rserver en mmoire
new Box();
new int[10]; // stocker 10 int + la taille du tableau new Pixel(1,3); // utilise un constructeur Le terme de constructeur est mal choisi: initialiseur serait mieux
Ce que retourne l'oprateur new est la rfrence qui permet d'accder l'objet allou en mmoire
30 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Dsallocation mmoire
Elle n'est pas gre par le programmeur, mais par un GC (Garbage Collector) Les objets qui ne sont plus rfrencs peuvent tre rcuprs par le GC, pour recycler l'espace mmoire qu'ils occupent Un mme objet peut tre rfrenc par plusieurs variables Il faut qu'aucune variable ne rfrence plus un objet pour qu'il soit rclam Les variables cessent de rfrencer un objet
Quand on leur affecte une autre valeur, ou null Quand on quitte le bloc o elles ont t dfinies: elles meurent, disparaissent... (sur la pile)
31
Lorsqu'il y a besoin de place supplmentaire ou quand il le dcide Pour viter une fragmentation de la mmoire, il dplace les objets en mmoire (zone des vieux des rcents , etc.) Les rfrences ne sont pas des adresses (indirection)
32 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
package fr.umlv.ir1.basics; Il permet de dfinir un espace de nommage qui donne un nom complet la classe: fr.umlv.ir1.basics.MyClass L'organisation des classes dans les rpertoires du systme de fichier doivent reflter l'organisation des paquetages: le rpertoire fr/umlv/ir1/basics contient la classe MyClass.java
Des directives d'importation (l o aller chercher les classes dont on se sert dans le code); ce n'est pas une directive d'inclusion!
import java.io.*; import java.util.Scanner; Les classes du paquetage java.lang sont visibles par dfaut
33 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
(Trs vite) indispensable: regrouper les classes en paquetages Obligatoire: avoir une hirarchie de rpertoire isomorphe la hirarchie des paquetages -d : rpertoire de Sparer les sources des classes
destination des classes -cp : rpertoire o trouver [code$] ls les classes compiles classes src [code$] ls src/fr/umlv/ir1/basics/ HelloWorld.java Pixel.java [code$] javac -d classes src/fr/umlv/ir1/basics/Pixel.java [code$] ls classes/fr/umlv/ir1/basics/ Pixel.class [code$] java -cp classes/ fr.umlv.ir1.basics.Pixel (1,3) false true
[code$] javac -cp classes -d classes src/fr/umlv/ir1/basics/HelloWorld.java
[code$] java -cp classes/ fr.umlv.ir1.basics.HelloWorld Bonjour vous les IR1! (1,3) false true Les deux si la compilation 34 a besoin d'autres classes Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
class MyClass
La classe sera accessible depuis toutes les classes du mme paquetage qu'elle (on parle quelque fois de visibilit de paquetage) La classe sera accessible de n'importe o (pourvu qu'on indique son nom de paquetage complet ou qu'on utilise la directive import)
Cette notion d'accessibilit sert dfinir des composants de plus grande granularit que les classes,
Ils dfinissent ce qui sera stock dans chaque objet de cette classe Elles dfinissent les actions/fonctionnalits/comportements accepts par les objets de cette classe Chaque mthode deux parties:
Sa signature (type de retour, nom, types des paramtres Son code, qui est constitu de blocs imbriqus
Il peut galement y avoir aussi quelques blocs d'intitalisation, constructeurs ou autres classes internes ...
Une variable locale est visible dans le bloc dans lequel elle est dclare Les paramtres des mthodes sont considrs comme des variables locales 2 variables de mme nom doivent tre dans des blocs disjoints
public class =ocal7ariable ! private static double su&(double01 values double su&=0.0; for(double v(values ! su&"=v; # // v n>est plus accessible return su&; # // values et su& pas accessible public static void &ain($trin/01 ar/s ! sum(new double01!3*6*?*2# ; # # !
37
Le mot-cl final signifie en Java affectation unique Il s'applique sur la variable qui est dclare Un objet ou un tableau final peut avoir ses champs ou ses lments modifis
public class @inal<xa&ple ! public static void &ain($trin/01 ar/s ! final int val; if (ar/s.len/th==3 val=6; else val=?; val = 0; // error( variable val &i/ht alread% have been assi/ned final $trin/01 tab = ar/s; for(int i=0;i<ar/s.len/th;i"" tab0i1='toto'; // oA* car cela ne chan/e pas la r)f)rence
38 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Leur existence et leur dure de vie sont associes aux objets (ou au pire la classe elle-mme)
Tandis que les variables locales sont associes une excution de la mthode qui les utilise... sur la pile!
Les champs possdent une valeur par dfaut qui leur est affecte lors de la cration d'un objet
0 pour les types numriques primitifs false pour les boolens null pour les types rfrence Tandis que les variables locales doivent ncessairement tre initialises avant d'tre utilises
39 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Tous les membres ont une accessibilit qui est spcifie la dclaration par un modificateur De manire complmentaire celui de la classe, il permet de dterminer qui, parmi ceux qui ont accs la classe A, ont accs ce membre
private : accessible uniquement depuis l'intrieur de la classe A Par dfaut (pas de modificateur) : accessible depuis toutes les classes qui sont dans le mme paquetage que A protected : accessible depuis toutes les classes qui sont dans le mme paquetage que A, et galement depuis celles qui ne sont pas dans le mme paquetage mais qui hritent de la classe A public : accessible depuis n'importe o
40 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
p.x, p0.sameAs(p1);
Le compilateur regarde le type dclar de la variable (ici p ou p0) et vrifie que le membre (ici x ou sameAs) existe. Le compilateur vrifie galement les droits d'accessibilit Un champ et une mthode peuvent avoir le mme nom this reprsente l'instance courante
public class )i*el { private int *' private int y' public )i*el(int *- int y) { this.* + *' this.y + y' ( public boolean same5s()i*el p) { return (t6is.*++p.*) 11 (t6is.y++p.y)' ( public static void main(String[] args) { )i*el p, + new )i*el(,-,)' )i*el p% + new )i*el(%-2)' boolean 7 + p,.sameAs(p%)' // 3alse ( ( class .t6er8lass { public static void main(String[] args) { )i*el p, + new )i*el(,-,)' p.same5s(p)' // true p,.* + %' // error( x has private 41 ( // access in ;ixel Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Cration d'instances
Une instance, ou un objet, d'une classe est cre en 3 temps Pixel p1 = new Pixel(1,3);
new est l'oprateur d'instanciation: comme il est suivi du nom de la classe, il sait quelle classe doit tre instancie
Il initialise chaque champ sa valeur par dfaut Il peut excuter un bloc d'initialisation ventuel Il retournera la rfrence de l'objet ainsi cr
Pixel est le nom de la classe (1,3) permet de trouver une fonction d'initialisation particulire dans la classe, qu'on appelle un constructeur
Constructeur
Un constructeur est une mthode particulire, qui sert initialiser un objet une fois que la mmoire est rserve par new
Permet de garantir des invariants sur un objet sont conservs, par exemple pour initialiser un objet avec des valeurs particulires
Le faire avec une mthode normale ne garantirait pas qu'on accde pas l'tat de l'objet avant son initialisation Le constructeur a le mme nom que la classe et pas de type de retour
class Bo* { pri"ate int 3ield' pu7lic static "oid main(String[] a){ Bo* 7 + ne9 Bo*()' ( (
43 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
En l'absence de constructeur explicitement dfini, le compilateur ajoute un constructeur public sans paramtre
Ils ont typiquement des rles diffrents et offrent des services complmentaires l'utilisateur, par exemple:
new Pixel(1,3) cre un pixel avec les coordonnes explicites new Pixel() cre un pixel avec les coordonnes l'origine new Pixel(1) cre un pixel sur la diagonale (x == y), etc.
public class )i*el { private int *' private int y' public )i*el(int *- int y) { this.* + *' this.y + y' ( public )i*el() { t6is(,-,)' ( public )i*el(int ") { this("- ")' 44 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Quand c'est possible, il est prfrable qu'il y en ait un le plus gnral et que les autres y fassent appel
Plutt que de dupliquer le code dans plusieurs constrcuteurs L'appel un autre constructeur de la mme classe se fait par this(...)
Champ constant
Comme pour les variables locales, il est possible de dclarer un champ avec le modificateur final.
Cela signifie qu'il doit avoir une affectation unique Le compilateur vrifie que il a bien t initialis, et ce quelque soit le constructeur mais galement qu'il n'a t affect qu'une seule fois
public class )i*el { private final int *' private int y' public )i*el(int *- int y) { this.* + *' this.y + y' ( public )i*el() { // error( final field x &a% not // have been initiali8ed ( public )i*el(int ") { this("- ")' ( public static void main(String[] a){ )i*el p + ne9 )i*el(%)' p.* + ,' // error( final field x // cannot been assi/ned ( ( 45
Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Surcharge
Objectif: fournir plusieurs dfinitions pour la mme mthode Le compilateur doit pouvoir trouver celui qui convient le mieux au site d'appel , c'est dire au nombre et au type des arguments Si aucune mthode ne correspond exactement, le compilateur peut prendre une mthode approche en fonction du typage
Le typage et la surcharge
Les types dclars des variables pevent quelque fois tre ordonns par une relation de sous-typage
Li aux classes, aux interfaces, aux classes abstraites, l'hritage... byte < short < int < long < float < double char < int
En rgle gnrale, il est prfrable d'utiliser la surcharge entre deux mthodes quand elles ont la mme smantique
float sqrt(float value) {...} // et double sqrt(double value) {...} // OK void remove(Object value) {...} // et void remove(int index) {...} // KO (liste)
47
Ambiguit de surcharge
public class ."erloading { public static void m(int i- lon/ l) { System.out.println("m(int- long)")' ( public static void m(lon/ l- int i) { System.out.println("m(long- int)")' ( public static void main(String[] args) { int i + %' lon/ l + %:' m(i-l)' // m(int- long) m(l-i)' // m(long- int) m(i-i)' // reference to & is a&bi/uous* // both ðod &(int*lon/ and ðod &(lon/*int ( (
&atch
Dclars avec le mot-cl static, les membres statiques sont lis la classe et non une instance particulire (un objet)
Champs: sa valeur n'est pas propre un objet mais la classe (le champ lui-mme, et bien sr sa valeur, est la mme pour tous les objets de la classe)
Mthodes: son code ne dpend pas d'un objet de la classe et peut tre excut mme si aucun objet existe (e.g. main) Classes internes
Tout code utilis dans les membres statiques ne peut pas faire rfrence l'instance courante (this)
49 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Le mystre de println()...
public static void main(String[] args) { System.out.println("Hi les gee;s&")'// Bi les /eeAs!
void java.io.PrintStream.println(String x)
System.out.println(<c<)' System.out.println(0.=3)' .7 ect o + new .7 ect()' System.out.println(o)' int[] ta7 + new int[=]' System.out.println(ta7)' )i*el p% + new )i*el(%-2)' System.out.println(p%)'
// c // 3.2
void java.io.PrintStream.println(char x)
void java.io.PrintStream.println(float x)
// Cava.lan/.DbCectEFa+55?a1
void java.io.PrintStream.println(Object x)
// 0GE3FaHc?eF
void java.io.PrintStream.println(Object x)
// ;ixelE30cf3cH0
50 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
void java.io.PrintStream.println(Object x)
Comment a marche?
chaque valeur de type primitif (boolean char double float int long) Aux chanes de caractres (String et char[]) Aux objets (Object)
Cela induit une relation de sous-typage : A < Object A dfinit un sous-type de Object On peut donc appliquer sur A ce qu'on sait faire sur Object
51
Dans la classe Object, toString() affiche une chane construite par Pour notre cas, si Pixel p = new Pixel(1,3);
Comme p est un sous-type de Object, l'appel println(p) excute la mthode println(Object x) sur l'objet p, ce qui appelle String.valueOf(p) qui lui-mme retourne p.toString() Comme il n'y a pas de mthode toString() explicitement dfinie dans Pixel, c'est la mthode toString() de Object hrite dans Pixel qui 52 est appele. CQFD. Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
L o c'est fort...
Quand une mthode m() est appele sur une variable v qui contient une rfrence
Le compilateur vrifie qu'il y a bien une mthode m() dfinie pour le type dclar de la variable v ( au pire, je sais faire ) La JVM ( l'excution) recherche une dfinition pour cette mthode m() qui soit la plus prcise possible,i.e., la plus proche du type rel de la rfrence contenue dans v Par exemple, si Object v = new Pixel(1,3);
C'est possible car Pixel est un sous-type de Object v est dclare de type Object (info compile time), mais contient en ralit une rfrence un objet de type Pixel (info run time)
Si m() est la mthode toString(), le compilateur dit banco pour Object.toString() et la JVM recherche Pixel.toString()
53
Et voil le travail...
public class )i*el { demande au compilateur de // ... vrifier qu'on est bien en train >."erride de redfinir une mthode qui public String toString() { sinon serait hrite return "("/*/"-"/y/")"' ( public static void main(String[] args) { .7 ect o + new )i*el(%-2)' System.out.println(o)' // (1*6 // et a fortiori )i*el p + new )i*el(=-?)' System.out.println(p)'
void java.io.PrintStream.println(Object x)
// (2*F
54 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
void java.io.PrintStream.println(Object x)
Le sous-typage
Le comportement dpend de l'objet rellement contenu dans la variable L'affichage d'un objet est diffrent de l'affichage d'un Pixel Mais les deux peuvent s'afficher... Ils disposent tous les deux de la mthode toString()
Sur lesquels un ensemble de mthodes est disponible Mais dont la dfinition exacte dpend du sous-type La mthode finalement excute sera la plus prcise possible
55
Exemple: toute figure a une surface, mais la surface d'un carr ne se calcule pas comme la surface d'un cercle...
byte < short < int < long < float < double char < int
On a vu que toute classe A hrite de la classe Object, et dfinit ainsi un type A qui est sous-type du type Object L'hritage dfinit des sous-types:
Soit explicitement: class Student extends Person { ... } Soit implicitement Pixel ou int[] hritent de Object Une interface dclare les mthodes applicables par les objets des classes qui l'implmentent Une classe implmente l'interface en dfinissant ses mthodes: class Carre implements Mesurable { ... }
56
L'hritage
Consiste dfinir une classe, dite classe drive ou classe fille, partir d'une autre classe, dite classe de base ou classe mre, en rcuprant automatiquement dans la classe drive tous les membres de la classe de base, et en lui en ajoutant ventuellement de nouveaux membres Pixel
x:int y:int moveTo(int,int)
public class )i*el { private int *' private int y' public void mo"e@o(int ne9A- int ne9B) { this.* + ne9A' this.y + ne9B' ( ( public class 8olored)i*el extends )i*el { private b%te[] rg7' public b%te get$ed() { return rg7[,]' ( public b%te getCreen() { return rg7[%]' ( public b%te getBlue() { return rg7[0]' ( (
Tout objet d'une classe drive est considr comme tant avant tout un objet de la classe de base
Tout objet d'une classe drive cumule les champs drivs dans la classe de base avec ceux dfinis dans sa propre classe
public static void main(String[] args) { )i*el p + new )i*el()' p.mo"e@o(%- %)' 8olored)i*el cp + new 8olored)i*el()' cp.mo"e@o(0- 0)' ( cp.get$ed()' // :ull;ointer<xception
#1 #2
x:1 y:1 #2
@class ColoredPixel
Si x n'est pas private dans Pixel, on peut dire this.x dans ColoredPixel
Ils peuvent tre masqus par la dfinition de champs qui ont le mme nom dans la classe drive
Si String x est dclar dans ColoredPixel, c'est celui qui sera considr dans cette classe quand on parle de this.x Il est possible de manipuler celui qui est masqu (s'il est accessible) par la notation super.x
public class 8olored)i*el extends )i*el { private b%te[] rg7' String *' void test() { System.out.println(this.*)' // null System.out.println(super.*)' // 0 59 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
La rsolution des champs est effectue par le compilateur, en fonction du type dclar de la variable qui contient la rfrence
public static void main(String[] args) { 8olored)i*el cp + new 8olored)i*el()' // le t%pe d)clar) de cp est Iolored;ixel System.out.println(cp.*)' // null
)i*el p + cp' // le t%pe d)clar) de p est ;ixel* &J&e si la r)f)rence // contenue dans p est celle d>un Iolored;ixel ( System.out.println(p.*)' // 0
60 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Si c'est possible de crer dans une classe hrite un champ qui a le mme nom qu'un champs d'une superclasse
C'est rarement trs utile, souvent une mauvaise ide, source d'erreur
class 5 { int * + %' ( class B extends 5 { String * + "DD"' (
super, c'est this vu avec le type de la super-classe super.super.x n'existe pas... Pas plus que ref.super ni ref.super.x...
En revanche, le transtypage (cast) permet d'accder en changeant le type dclar de la rfrence ref
class 8 extends B { boolean * + true' public static void main(String[] args) { 8 c + new 8()' System.out.println(c.*)' // true System.out.println(((B)c).*)' // 88 System.out.println(((5)c).*)' // 1 61 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Le transtypage de rfrence est le fait de considrer explicitement (forcer) une rfrence comme tant d'un type donn (qui n'est pas ncessairement le type de l'objet accessible via cette rfrence) La machine virtuelle vrifiera, l'excution, que le type en question est bien compatible et que voir cette rfrence comme tant de ce type l est possible; dans le cas contraire, l'excution provoque une ClassCastException
class 5 { ( class B extends 5 { ( class 8 extends B { ( .7 ect o' if(Eat6.random() F ,.=) o + "toto"' else o + new .7 ect()' String s + (String) o' // Io&pile touCours &ais a une // chance sur deux de lever une 62 // IlassIast<xception... Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
B 7 + new B()' 5 a + 7' // B 70 + a' // inco&patible t%pes B 70 + (B) a' // DK 8 c + (8) a' // IlassIast<xception
L'oprateur instanceof
x doit tre une (variable contenant une) rfrence ou null T doit rerpsenter un type Le rsultat vaut true si x n'est pas null et s'il peut tre affect dans T sans ClassCastException; sinon c'est false.
.7 ect o' String s' if(Eat6.random()F,.=) o + "toto"' else o + new .7 ect()' if (o instanceof String) s + (String) o' // DK...
Constructeurs et hritage
La construction (initialisation) de toute instance d'une classe dbute par la construction (initialisation) d'une instance d'Object
En pratique, tout constructeur dbute par un appel au constructeur de sa super-classe: super() Doit obligatoirement tre la premire instruction du constructeur Le constructeur implicite (ajout par le compilateur) fait appel au constructeur sans argument de la super-classe
public class )i*el { private int *' private int y' public )i*el(int *- int y) { this.* + ne9A' this.y + ne9B' public class 8olored)i*el extends )i*el { private b%te[] rg7' ( public Iolored;ixel( ! // ... // super( ; // Ionstructeur ;ixel( is undefined ( super(,-,)' // DK; note8 Lue x et % sont private! rg7 + new b%te[2]' 64 # Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Constructeurs et initialisations
Il faut voir le constructeur d'une classe comme une tape dans l'initialisation des objets de cette classe:
Commence par l'initialisation des champs de l'objet en tant qu'instance de la super-classe : c'est l'objectif de l'appel super(...) Ensuite il se charge d'initialiser les objets qui lui sont propres (en tant qu'instance de la classe drive) L'appel super ne peut pas utiliser des champs dont l'existence ou la valeur dpendrait de l'instance de la classe drive...
public class 8olored)i*el extends )i*el { private int " + ,' private static int s + ,' public 8olored)i*el() { // super("-")' // errorG cannot re3erence " 7e3ore supertype constructor 6as 7een called super(s-s)' // .H ( 65 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
En plus des champs, en tant que membres , la classe drive hrite des mthodes de la classe de base Seuls les constructeurs ne sont pas hrits
Attention: le code (smantique) d'une mthode de la super classe peut ne plus tre correct dans la classe drive
moveTo() hrite dans ColoredPixel a une smantique correcte Mais que dire de toString() qui donne une reprsentation textuelle? Que dire de sameAs() qui compare un pixel un autre pixel?
Dans certains cas, il faut donner une nouvelle dfinition de la mme mthode utiliser pour la classe drive
66
Redfinition de mthode
Mme nom, mmes arguments, code diffrent L'annotation @Override demande au compilateur de vrifier
public class 8olored)i*el extends )i*el { private b%te[] rg7' // ... >."erride public String toString() { return super.toString()/"["/rg7[,]/"G"/rg7[%]/"G"/rg7[0]/"]"' ( public static void main(String[] args) { 8olored)i*el cp + new 8olored)i*el(0-0)' System.out.println(cp)' // (3*3 00(0(01 )i*el p + new )i*el(=-=)' System.out.println(p)' // (2*2 .7 ect o + new 8olored)i*el(0-0)' System.out.println(o)' // (3*3 00(0(01 ( 67 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Les champs dfinis dans les classes drives sont tous prsents dans l'objet instance de la classe drive
Mme s'ils ont mme nom et mme type On peut accder celui immdiatement suprieur par super.x La rsolution dpend du type dclar du paramtre a permet d'accder chacun d'entre eux par transtypage
On peut accder celle immdiatement suprieure par super.m() La rsolution est faite en deux temps
Compile-time: on vrifie que c'est possible sur le type dclar Runtime: on cherche la plus prcise tant donne le type rel
68 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Si la signature de la mthode qu'on dfinit dans la classe drive n'est pas le mme que celle de la classe de base, il s'agit de surcharge:
class 5 { void m%() { ... ( void m0() { ... ( )i*el m2() { ... ( void mI()i*el p) { ... ( ( class B extends 5 { >."erride void m%() { ... ( void m0(int a) { ... ( >."erride 8olored)i*el m2() { ... ( >."erride void mI()i*el p) { ... ( void mI(8olored)i*el p) { ... ( (
// // // // //
Quand on redfinit une mthode m() dans B alors qu'elle tait dfinie dans A, o B est un sous-type de A
L'objectif est de lui donner une dfinition plus prcise (mieux adapte B qu' A), de sorte qu'elle soit appele run-time, y compris si compile-time le compilateur n'avait vu que celle qui est dfinie dans A
Le compilateur est sens viter les mauvaises surprises (dcouvrir un problme run-time): c'est ce qui gouverne les rgles
Une mthode d'instance ne peut pas redfinir une mthode static L'accessibilit de la mthode redfinie ne peut pas tre plus restrictive Le type de retour ne peut pas tre d'un super-type (rfrences) Les exceptions propages ne peuvent tre que d'un sous-type
70 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Le cas de sameAs...
Donner une reprsentation textuelle plus prcise dans ColoredPixel : c'est facile (mme signature)
Actuellement, la mthode hrite est fausse! Redfinition: pas si simple avec la signature de sameAs()
// public boolean same5s(8olored)i*el p) { // Surc6arge et pas redJ3inition >."erride public boolean same5s()i*el p) { // return (*++p.*) 11 (y++p.y) 1 p.rg7[,]+rg7[,] ... // 5Ke& * and yG pri"ate access in )i*el // return super.same5s(p) 11 p.rg7[,]+rg7[,] ... // 5Ke& rg7 is not a 3ield // return super.same5s(p) 11 ((8olored)i*el)p).rg7[,]++rg7[,] ... // 8ompile- mais si p n<en est pas un 8olored)i*el... 5Ke& // #l 3aut utiliser instanceo3... 71 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
La mthode equals()
De la mme manire qu'il existe une mthode toString() dans la classe Object, que toute sous-classe peut redfinir Il existe dans Object une mthode equals(Object obj) dont le contrat est clairement tabli par la documentation
Par dfaut, elle teste l'galit primitive des rfrences (mme objet) C'est celle-l qu'il faut redfinir!
public class 8olored)i*el extends )i*el { private b%te[] rg7' EDverride public boolean eLuals(.7 ect o7 ) { if(&(o7 instanceof 8olored)i*el)) return false; 8olored)i*el cp + (8olored)i*el) o7 ' return super.eLuals(o7 ) 11 rg7[,]++cp.rg7[,] 11 rg7[%]++cp.rg7[%] 11 rg7[0]++cp.rg7[0]' ( 72 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
public class )i*el { private int *- y' // ... >."erride public boolean eLuals(.7 ect o7 ) { if(&(o7 instanceof )i*el)) return false' )i*el p + ()i*el) o7 ' return (*++p.*) 11 (y++p.y)' ( (
Reflexive
Pour toute rfrence x non nulle, x.equals(x) vaut true Pour toutes rfrences x et y non nulles, x.equals(y) ssi y.equals(x) Pour toutes rfrences x, yet z non nulles, si x.equals(y) et y.equals(z) alors x.equals(z )
Symtrique
Transitive
Cohrente
Tant qu'on ne modifie pas les valeurs utilises pour tester l'galit, la valeur de x.equals(y) retourne toujours la mme valeur
Pour toute rfrence x non nulle, x.equals(null) vaut false Redfinition de equals() implique en gnral redfinition de hashCode()
73
Demandez un Pixel en (2,2) s'il est gal un ColoredPixel en (2,2), il dira que oui!
Demandez un ColoredPixel magenta en (2,2) s'il est gal un Pixel en (2,2), il dira que non!
Je trouve que ce code est acceptable... il faut juste tre conscient de la nuance...
public class 8olored)i*el extends )i*el { // ... public static void &ain($trin/01 ar/s ! DbCect o1 = new ;ixel(3*3 ; DbCect o3 = new Iolored;ixel(3*3 ; $%ste&.out.println(o1.eLuals(o3 ; // true $%ste&.out.println(o3.eLuals(o1 ; // false # (
74
La mthode hashCode()
Cette mthode est utlise lorsqu'on stocke des objets dans une table de hachage (exemple java.util.HashMap) Elle tablit galement un contrat (de pair avec equals())
public int hashCode() tant donne une excution de la JVM, diffrents appels la mthode hashCode() doivent retourner la mme valeur tant qu'on ne modifie pas les valeurs utilises pour tester l'galit (equals()) Si deux objets sont gaux au sens de equals(), la mthode hashCode() appele sur les deux doit produire la mme valeur Deux objets distincts au sens de equals() peuvent avoir des hashCode() identiques (c'est une collision ), mais fournir des hashCode() distincts pour des objets distincts au sens de equals() amliore la performance des tables de hachage.
75 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Les ensembles, les tables de hachage, etc. Si equals est redfinie, mais pas hashCode, voil ce qui arrive
i&port Cava.util.Bash$et; public class )i*el { // ... public static void main(String[] args) { )i*el Dero + new )i*el(,-,)' )i*el de3 + new )i*el()' Has6Set set + new Has6Set()' set.add(Dero)' System.out.println(set.contains(de3))' // false System.out.println(Dero.6as68ode())' System.out.println(de3.6as68ode())' ( System.out.println(Dero.eLuals(de3))' // 12330521F2 // 23?1+6151 // true
76 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
77
Il signifie que la mthode ne pourra pas tre redfinie dans une sous-classe Peut tre utile pour garantir qu'aucune autre dfinition ne pourra tre donne pour cette mthode (scurit)
Il devient alors impossible d'hriter de cette classe Les mthodes se comportent comme si elles taient final
Les interfaces
Un type Une structure de donnes pour les instances (les champs) Des mthodes avec leur code (leur dfinition)
Une interface ne peut pas tre instancie Elle est destine tre implmente par des classes
qui elle donnera son type Qui fourniront des dfinitions pour les mthodes dclares (code)
79 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Donner un type commun des classes diffrentes pour en faire un mme usage Exemple:
Manipuler des tableaux de trucs qui ont chacun une surface Faire la somme des surfaces des trucs qui sont dans le tableau
public interface Sur3acea7le { public double sur3ace()' (
public class 5lgo.n@rucs { public static double totalSur3ace(Sur3acea7le[] array) { double total + ,.,' for($urfaceable truc G array) total /+ truc.surface( ' return total' ( (
80
Utilisation d'interface
L'algo de la mthode totalSurface(Surfaceable[] array) fonctionne indpendamment de la classe relle des objets qui sont stocks dans array: c'est le sous-typage La mthode surface() effectivement appele sur les objets contenus dans le tableau sera la plus prcise possible, en fonction du type rel de cet objet: c'est le polymorphisme
public class 5lgo.n@rucs { public static double totalSur3ace(Sur3acea7le[] array) { ... ( public static void main(String[] args) { Mectan/le rectangle + new $ectangle(0-=)' $Luare sLuare + new SLuare(%,)' Iircle circle + new 8ircle(%)' $urfaceable[] t + {rectangle- sLuare- circle(' System.out.println(totalSurface(t))' // 116.1?12+35262H+H (
81
Implmentation d'interface
public class $Luare i&ple&ents $urfaceable { private final double side' public SLuare(double side) { this.side + side' public class Mectan/le i&ple&ents $urfaceable { ( private final double 6eig6t' >."erride private final double 9idt6' public double sur3ace() { public $ectangle(double 6eig6t- double 9idt6) { return side * side' this.6eig6t + 6eig6t' ( this.9idt6 + 9idt6' ( ( >."erride public double sur3ace() { return 6eig6t * 9idt6' ( ( public class Iircle i&ple&ents $urfaceable { private final double radius' public 8ircle(double radius) { this.radius + radius' ( >."erride public double sur3ace() { return Eat6.PI * radius * radius' 82 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Toutes les mthodes sont public interface Sur3acea7le { double sur3ace()' // eLuivaut N abstract public
public interface # { Tous les champs sont int field + %,' // eLuivaut N public final static public final static int field
+ %,'
On ne peut que dclarer des variables avec leur type Ces variables pourront reevoir des rfrences des objets qui sont des instances d'une classe qui implmente l'interface
83
Mot cl implements
public class Mectan/le i&ple&ents $urfaceable { ... (
Mot cl extends
public interface )ainta7le extends Sur3acea7le { double paint(b%te[] color- int layers)' (
Le type SurfaceableAndMoveable dfinit un sous-type des deux types Surfaceable et de Moveable (sous-typage multiple)
SurfaceableAndMoveable < Surfaceable et SurfaceableAndMoveable < Moveable Ces deux dernires n'ont aucune relation entre-elles
85 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
public class $olidIircle extends Iircle i&ple&ents ;aintable- ,oveable { private final )oint center' public Solid8ircle()oint center- double radius) { super(radius)' this.center + center' ( >."erride // ;our pouvoir i&pl)&enter ;aintable public double paint(b%te[] color- int layers) { // doOhe;aintin/Pob(color*la%ers ; return layers * sur3ace()' // $olidIircle < Iircle < $urfaceable ( >."erride // ;our pouvoir i&pl)&enter ,oveable public void mo"e@o(int *- int y) { center.mo"e@o(*-y)' ( public static void main(String[] args) { Solid8ircle sc + new Solid8ircle(new )oint(,-,)- 2)' 8ircle c + sc' double d + c.sur3ace()' // $olidIircle < Iircle )ainta7le p + sc' p.paint(new b%te[]{,-,-,(-0)'// $olidIircle < ;aintable Eo"ea7le m + sc' m.mo"e@o(%- %)' // $olidIircle < ,oveable 86 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Vrifications du compilateur
Toutes les mthodes dclares (abstract) dans l'ensemble des interfaces dont on revendique l'implmentation doivent tre implantes
Mme si on a mis la visibilit par dfaut dans l'interface, le compilateur y ajoute public abstract
Que se passe t il si plusieurs mthodes de mme nom et mme signature de diffrentes interfaces doivent tre implmentes dans la mme classe?
87 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Object
Qui pourraient provenir de deux classes dont on hrite et qui devraient coexister dans un mme objet!
A x:int C x:int
B x:int
#1
@class C
? ? ?
C c #1
Au mme titre que l'implmentation multiple d'interfaces On rcupre par hritage uniquement
des dclarations de mthodes (qui ne possdent pas de dfinition) des constantes dont la porte est limite l'interface dans laquelle elles sont dfinies (espace de nom)
88 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
pour crer un nouveau type qui est une sorte particulire de classe de base
Pour regrouper un ensemble de fonctionalits qui pourront tre implmentes par des instances qui en implantent dj d'autres (ou qui hritent d'une autre classe)
Les mthodes doivent toutes tre abstraites Elles ne peuvent tre que publiques
Les mthodes doivent tre dfinies (leur code) Elles peuvent avoir des modificateurs de visibilits diffrents
Il s'agit d'une classe qui peut avoir des mthodes abstraites Elle est considre comme partiellement implante, donc non instanciable Elle peut ventuellement n'avoir aucune mthode abstraite
90 Le mot-cl abstract fait qu'elle n'est pas instanciable Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
... sur lequel je sais faire des choses, mais pas tout!
public class 5lgo.n@rucs { public static double totalSur3ace($urfaceable[] array) { double total + ,.,' for(Sur3acea7le truc G array) Le code de surface() ne peut tre dfini total /+ truc.surface()' que dans la classe concrte return total' ( public static Sur3acea7le t6eBigger($urfaceable[] array) { Sur3acea7le 7igger + array[,]' for(int i + %' iParray.lengt6' i//) { if (array[i].bi//erOhan(bi//er ) Mais je peux crire un code pour 7igger + array[i]' biggerThan() qui ne dpend pas de ( return 7igger' cette classe concrte ( public static void main(String[] args) { $ectangle rectangle + new $ectangle(0-=)' SLuare sLuare + new SLuare(%,)' 8ircle circle + new 8ircle(%)' Sur3acea7le[] t + {rectangle- sLuare- circle(' System.out.println(totalSurface(t))' // 116.1?12+35262H+H System.out.println(theBigger(t))' // $LuareEa5eb6Ha 91 ( Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
L'implmentation de la mthode biggerThan() marchera ds qu'on l'appelera sur un objet (instance) d'une classe concrte, puisque celle-ci aura donn l'implmentation de la mthode public abstract class Sur3acea7le { surface().
public abstract double sur3ace()' public boolean 7igger@6an(Sur3acea7le 7igger) { return sur3ace() F 7igger.sur3ace()' (
public class $ectangle extends Sur3acea7le { ... public class 8ircle extends Sur3acea7le { ( ... public class SLuare extends Sur3acea7le { ( private final double side' public SLuare(double side) { this.side + side' ( >."erride public double sur3ace() { return side * side' (
92
Les Exceptions
Mcanisme qui permet de reporter des erreurs vers les mthodes appelantes
Problme en C :
prvoir une plage de valeurs dans la valeur de retour pour signaler les erreurs. Propager les erreurs manuellement
En Java comme en C++, le mcanisme de remont derreur est gre par le langage.
Exemple d'exception
Un exemple simple
public class ExceptionExample { public static char charAt(char[] array,int index) { return array[index]; } public static void main(Strin [] ar s) { char[] array!ar s["]#to$harArray(); charAt(array,"); }
Lors de lexcution :
$%&eclipse&'or(space&)ava*avanc+,)ava ExceptionExample Exception in thread -main- )ava#lan #Array.ndex/ut/01oundsException% " at ExceptionExample#main(ExceptionExample#)ava%23)
94 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
$%&eclipse&'or(space&)ava*avanc+,)ava ExceptionExample toto Exception in thread -main- )ava#lan #.lle alAr umentException% bad index 2""" at ExceptionExample#charAt(ExceptionExample#)ava%27) at ExceptionExample#main(ExceptionExample#)ava%8")
95 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Types d'exceptions
Il existe en Java tout une hirarchie de types d'exceptions
Throwable
Error
Exception
RuntimeException
problme d'entre/sortie :
IOException, AWTException
problme de ressource :
OutOfMemoryError, StackOverflowError
IOException
101
La directive throws
Indique qu'une exception peut-tre leve dans le code mais que celui-ci ne la gre pas (pas de try/catch).
public static void 0(Strin author) thro's /h9oException { i0 (-dan bro'n-#e@uals(author)) thro' ne' /h9oException(-oh no-); } public static void main(Strin [] ar s) { try { 0(ar s["]); } catch(/h9oException e) { try;o=ecover(); }
throws n'est obligatoire que pour les Exception pas les erreurs (Error) ni pour ou les runtimes (RuntimeException)
103 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
catch si l'on peut reprendre sur l'erreur et faire quelque chose de cohrent (appliquer une action corrective) Sinon throws pour propager l'exception vers celui qui a appel la mthode qui fera ce qu'il doit faire
Un exemple
La mme exception peut tre capture ou propage selon le contexte
public static Ionfi/ initIonfi/($trin/ user:a&e throws GD<xception ! Ionfi/ conf = null; @ileGnput$trea& fis = null; tr% ! fis = new @ileGnput$trea&(user:a&e"'Qconfi/' ; conf = new Ionfi/(user:a&e ; # catch (@ile:ot@ound<xception e ! // no confi/ file for this user... e.print$tacAOrace($%ste&.err ; fis = new @ileGnput$trea&('defaultQconfi/' ; conf = new Ionfi/(user:a&e ; } readConfFromInputStream(conf*fis ; 0is#close(); return conf; }
Le bloc finally
Sert excuter un code quoi qu'il arrive (fermer un fichier, une connexion, librer une ressources)
public class :inallyExceptionExample { public static void main(Strin [] ar s) { =eentrantAoc( loc( ! ne' =eentrantAoc((); loc(#loc((); try { doSomethin (); } 0inally { loc(#unloc(() } } }
Exception et StackTrace
Lors de la cration d'une exception, la VM calcule le StackTrace Le StackTrace correspond aux fonctions empiles (dans la pile) lors de la cration Le calcul du StackTrace est quelque chose de coteux en performance.
Permet de lever une exception suffisamment prcise tout en respectant une signature fixe
Dsencapsulation :
public static void caller() thro's /h9oException { Exception$hain chain!ne' Exception$hain(); try { chain#close(); } catch(./Exception e) { ;ho'able t!e# et$ause(); i0 (t instanceo0 /h9oException) thro' (/h9oException)t; ###
110
Le mot-cl assert
Le mot-cl assert permet de s'assurer que la valeur dune expression est vraie Deux syntaxes : assert test; assert test : mesg;
assert i!!); assert i!!)%-i not e@uals to )-;
Par dfaut, les assert ne sont pas excuts, il faut lancer java -ea (enable assert)
assert et AssertionError
Si le test boolen du assert est faux, la VM lve une exception AssertionError
public class AssertExample { private static void chec((Aist list) { assert list#isEmpty() 55 list#index/0(list# et("))C!*2; } public static void main(Strin [] ar s) { Aist list!ne' 1adAist.mpl(); list#add(7); chec((list); ### } }
Exceptions et programmeur
Que son code est bien utilis (pr-condition) Que l'tat de l'objet est bon (pr-condition) Que le code fait ce qu'il doit faire (post-condition/invariant)
Habituellement, les :
Exemple
public class Stac( { public Stac((int capacity) { array!ne' int[capacity]; } public void push(int value) { i0 (top,!array#len th) thro' ne' .lle alStateException(-stac( is 0ull-); array[top66]!value; assert array[top*2]!!value; assert top,!" HH top4!array#len th; } public int pop() { i0 (top4!") thro' ne' .lle alStateException(-stac( is empty-); int value!array[**top]; assert top,!" HH top4!array#len th; return value; } private int top; private 0inal int[] array; }
Pr-condition
Post-condition
Invariant
Utilisation de Javadoc
$%&)ava*avanc+,)avadoc src&Stac(#)ava Aoadin source 0ile src&Stac(#)ava### $onstructin Lavadoc in0ormation### Standard Boclet version 2#G#"*beta7 1uildin tree 0or all the pac(a es and classes### Meneratin Stac(#html### Meneratin pac(a e*0rame#html### ###
StrackTrace et optimisation
Pour des questions de performance, il est possible de pr -crer une exception
public class Stac(;raceExample { public static void 0() { thro' ne' =untimeException(); } public static void () { i0 (exception!!null) exception!ne' =untimeException(); thro' exception; } private static =untimeException exception; public static void main(Strin [] ar s) { 0(); << 2"" """ appels, moyenne()!72"N ns (); << 2"" """ appels, moyenne()!2E3 ns } }
119 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Appel de mthode
L'algorithme d'appel de mthode s'effectue en deux temps 1) A la compilation, on c erc e la mt ode la mieux adapte
!n rec erc e les mt odes applica"les #celles $ue l'on peut appeler) Parmi les mt odes applica"les, on rec erc e s'il existe une mt ode plus spcifi$ue #dont les param%tres seraient sous-t&pes des param%tres des autres mt odes)
') ( l'excution, on rec erc e l'implmentation de cette mt ode $ui soit la plus prcise tant donn le t&pe rel de l'o")et receveur de l'appel
Mthodes applicables
Ordre dans la recherche des mthodes applicables : *ec erc e des mt odes + nom"re fixe d'argument en fonction du sous-t&page , convertions primitifs *ec erc e des mt odes + nom"re fixe d'argument en permettant l'auto--un."oxing *ec erc e des mt odes en prenant en compte les varargs Ds qu'une des recherches trouve une ou plusieurs mthodes la recherche s'arrte
La mthode la plus spcifique est la mthode dont tous les paramtres sont sous-type des paramtres des autres mthodes
123 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Dans l'exemple, les deux mthodes add() sont applicables, aucune n'est plus prcise
124 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Surcharge et auto-[un]boxing
Le boxing/unboxing n'est pas prioritaire par rapport la valeur actuelle
public static void main(Strin [] ar s) { Aist list!### int value!7; .nte er box!value; list#remove(value); << appel remove(int) list#remove(box); << appel remove(/b)ect) public class Aist { public void remove(/b)ect value) { } public void remove(int index) { } }
125 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Surcharge et Varargs
Une mthode nombre variable d'arguments n'est pas prioritaire par rapport une mthode nombre fixe d'arguments
public class Oarar s/verloadin { private static int min(int### array) { } private static int min(double value) { } public static void main(Strin [] ar s) { min(8); << appel min(double) }
Late-binding
A l'excution, on recherche l'implmentation la plus prcise possible de la mthode identifie la compilation
public class R ! public static void &ain($trin/01 ar/s 4 b = new 4( ; I c = new S( ; c#m(b); // Rffiche I.&(R } } class 4 extends R ! #
class I ! public void &(R a ! $%ste&.out.println('I.&(R ' ; } } class S extends I ! public void &(4 b ! $%ste&.out.println('S.&(4 ' ; } } 128
Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Contient galement la plupart des classes, classes abstraites et interfaces sur les structures de donnes permettant de stocker des lments
Object.clone(),System.arraycopy(), Arrays.copyOf()
Les mthodes equals(), hashCode(), toString() ne sont pas redfinies sur les tableaux Arrays.equals(), Arrays.hashCode(),Arrays.toString() marchent pour Object et tous les types primitifs
int[] array!ne' int[]{8,7,G,E}; System#out#println(array); System#out#println(Arrays#toStrin (array)); System#out#println(array#hash$ode()); System#out#println(Arrays#hash$ode(array)); int[] array8!ne' int[]{8,7,G,E}; System#out#println(array8#hash$ode()); System#out#println(Arrays#hash$ode(array8)); System#out#println(array#e@uals(array8)); System#out#println(Arrays#e@uals(array,array8));
Tri
sort(byte[] a) sort(byte[] a, int 0rom.ndex, int to.ndex) ### 4;, sort(;[] a, $omparator4Q super ;, c) 4;, sort(;[] a, int 0rom.ndex, int to.ndex, $omparator4Q super ;, c)
Remplissage
0ill(boolean[] a, boolean val) 0ill(boolean[] a, int 0rom.ndex, int to.ndex, boolean val) ### 0ill(/b)ect[] a, /b)ect val) 0ill(/b)ect[] a, int 0rom.ndex, int to.ndex, /b)ect val)
132 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Ordre naturel
<0 si this est infrieur t ==0 si this est gal t >0 si this est suprieur t
public class )erson i&ple&ents Io¶ble<;erson. { private final String name- 3irstQame' private final int year' public )erson(String name- String 3irstQame- int year) { this.name + name' this.3irstQame + 3irstQame' this.year + year' ( >."erride public int co&pareOo(;erson p { int dQame + name.compare@o(p.name)' if(dQame &+ ,) return dQameR' int dSirstQame + 3irstQame.compare@o(p.3irstQame)' if(dSirstQame &+ ,) return dSirstQame' compareTo() et return year T p.year' equals() doivent ( tre compatibles >."erride public boolean eLuals(DbCect o { if (&(o instanceof )erson)) return falseT' )erson p+()erson)oR' return name.eLuals(p.name) 11 3irstQame.eLuals(p.3irstQame) 11 year ++ p.year' ( >."erride public String toString() { 134 return "(" / name / " " / 3irstQame / " " / year / ")"' Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle (
Affiche: [(Toto Titi 1990), (Toto Titi 1900), (Toto Abdel 1990), (Toto Zora 1990), (Dudu Titi 1950), (Paupau Seb 2010)] [(Dudu Titi 1950), (Paupau Seb 2010), (Toto Abdel 1990), (Toto Titi 1900), (Toto Titi 1990), (Toto Zora 1990)]
135 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Comparaison externe
Un ordre externe est un ordre valable juste un moment donn (rien de naturel et d'vident) La valeur de retour de compare suit les mmes rgles que compareTo Par exemple, pour notre classe Person,
L'ordre de la date de naissance L'ordre des prnoms, ou tout autre ordre moins naturel ...
136 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Ordre naturel
}
Affiche :
[(Dudu Titi 1950), (Paupau Seb 2010), (Toto Abdel 1990), (Toto Titi 1900), (Toto Titi 1990), (Toto Zora 1990)] [(Toto Titi 1900), (Dudu Titi 1950), (Toto Abdel 1990), (Toto Titi 1990), (Toto Zora 1990), (Paupau Seb 2010)]
137 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
Comparator inverse
Il existe deux mthodes static dans la classe java.util.Collections qui renvoie un comparator correspondant :
Map
BlockingQueue
139
Design
Sparation Interface/implantation Plusieurs implantations pour une interface permet d'obtenir en fonction de l'algorithme que l'on veut crire la meilleure complexit Deux classes contenant des algorithmes communs (mthodes statiques dans java.util.Arrays et java.util.Collections)
ensemble de donnes ensemble de donnes sans doublon ensemble ordonn et sans doublon ensemble ordonn, sans doublon avec prcdent suivant liste indexe ou squentielle file (FIFO) de donnes file bloquante de donnes double-ended queue
association sans relation d'ordre association avec cls tries association avec cls tries avec suivant/prcdent association accs concurrent
Iterator
Pour parcourir une collection, on utilise un objet permettant de passer en revue les diffrents lments de la collection java.util.Iterator<E> dfinie :
boolean hasNext() qui renvoie vrai s'il y a un suivant E next() qui renvoie l'lment courant et dcale sur l'lment suivant void remove() qui retire un lment prcdemment envoy par next() opration optionnelle
next() et NoSuchElementException
L'opration next() est scurise et lve une exception runtime NoSuchElementException dans le cas o on dpasse la fin de la collection (c-a-d si hasNext() renvoie false)
public static void main(Strin [] ar s) { $ollection4.nte er, c!ne' ArrayAist4.nte er,(); c#add(7); .terator4.nte er, it!c#iterator(); it#next(); it#next(); << 9oSuchElementException }
Exemple d'iterateur
Conceptuellement un iterateur s'utilise comme un pointeur que l'on dcale sur la collection
public static void main(Strin [] ar s) { $ollection4.nte er, c!ne' ArrayAist4.nte er,(); c#add(7); c#add(8); c#add(N); .terator4.nte er, it!c#iterator(); 0or(;it#has9ext();) { System#out#println(it#next()I8); } << a00iche E, N, 3 }
Pas toujours possible d'effectuer un parcours avec un index (Set, Queue, Deque) Problme de complexit (List squential)
Collection
Queue
Set
List
AbstractCollection
Deque
AbstractQueue
AbstractSet
AbstractList
AbstractSequentialList
147
Set
Collection Set AbstractSet SortedSet NavigableSet TreeSet CopyOnWriteArraySet HashSet EnumSet LinkedHashSet
148
AbstractCollection
Collection AbstractCollection Queue AbstractQueue BlockingQueue Deque LinkedList ArrayDeque PriorityQueue ConcurrentLinkedQueue
149 Etienne DURIS ESIPE-MLV Universit Paris-Est Marne-la-Valle
BlockingDeque
List
Collection
Map
ConcurrentMap
ConcurrentNavigableMap ConcurrentHashMap
NavigableMap
EnumMap
TreeMap ConcurrentSkipListMap
InputStream/OutputStream manipulent des octets (byte en Java) donc dpendant de la plateforme Reader/Writer manipulent des caractres (char en Java) indpendant de la plateforme mais qui ncessitent d'indiquer un codage des caractres On utilise l'une ou l'autre des versions en fonction de ce que l'on veut faire
InputStream
abstract int read() int read(byte[] b) int read(byte[] b, int off, int len) long skip(long n) void close()
Ferme le flux
Les mthodes read() sur un flux sont bloquantes s'il n'y a pas au moins un byte lire Il existe une mthode available() dans InputStream qui est sense renvoyer le nombre de byte lisible sans que la lecture sur le flux soit bloque mais mauvais le support au niveau des OS ( ne pas utiliser)
Attention, la lecture est une demande pour remplir le buffer, le systme essaye de remplir le buffer au maximum mais peut ne pas le remplir compltement
int read(byte[] b) renvoie le nombre de bytes lus int read(byte[] b, int off, int len) renvoie le nombre de bytes lus
InputStream et efficacit
Contrairement au C (stdio) par dfaut en Java, les entres sorties ne sont pas bufferiss Risque de gros problme de performance si on lit les donnes octets par octest Solution :
InputStream et IOException
Toutes les mthodes de l'input stream peuvent lever une IOException pour indiquer que
Il y a eu une erreur d'entre/sortie Que le stream est ferm aprs un appel close() Que le thread courant a t interrompu en envoyant une InterruptedIOException (cf cours sur la concurrence)
OutputStream
abstract void write(int b) void write(byte[] b) void write(byte[] b, int off, int len) void flush() void close()
Ferme le flux
Copie de flux
Reader
abstract int read() int read(char[] b) int read(char[] b, int off, int len) long skip(long n) void close()
Ferme le flux
Writer
abstract void write(int c) void write(char[] b) void write(char[] b, int off, int len) void flush() void close()
Ferme le flux
Ecrire un CharSequence
Writer append(CharSequence csq) Writer append(CharSequence csq, int start, int end)
Copie de flux