• Aucun résultat trouvé

Java-2-Bases

N/A
N/A
Protected

Academic year: 2022

Partager "Java-2-Bases"

Copied!
32
0
0

Texte intégral

(1)

JAVA

Cours et TP n° 02

Bases du langage Bertrand LIAUDET

SOMMAIRE

SOMMAIRE 1

JAVA – BASES DU LANGAGE 3

Les variables 3

Déclaration 3

Nom 5

Les 4 types de base (types primitifs ou types natifs) 5

Pointeur 5

Valeur par défaut 5

Valeurs littérales 6

Conversion : « cast » 6

Les constantes : final 6

Les opérateurs 6

Exemple 6

Les tableaux 8

Déclaration et instanciation 8

Utilisation 8

Tableau à dimension > 1 9

Taille du tableau : tab.length 9

Méthodes pour les tableaux 9

Les chaînes 11

Déclaration et instanciation 11

Exemple 11

Méthodes pour les chaînes 12

Les structures : vers la P.O.O. 14

Structure = Classe 14

Déclaration et instanciation 14

Utilisation d’une structure dans le Main 14

Tableau de structures 15

(2)

Vers la P.O.O : notion de constructeur 16 P.O.O 17

Contrôle de la séquence 19

Tests 19

Boucles 20

Débranchement 21

Fonctions 22

Remarques préliminaires 22

Exemple 22

Syntaxe 23

Qualificateurs 23

Usages des fonctions (ou méthodes) : 23

Mode de passage des paramètres 24

Récursivité 24

Saisie et affichage 25

Affichage 25

Saisie 25

Exception 26

Le problème 26

La solution : un canal dédié aux exceptions : throws et throw 26 La récupération d’exception : 1 try … N catch … 1 finally 27

Paquetage (package) 29

Présentation 29

Hiérarchie des paquetages standards 29

Syntaxe 29

Exemples 29

Deprecated 30

CLASSPATH 30

JAR 31

Présentation 31

JAR exécutable 31

Fabrication d’un JAR 31

Référence 31

TP 32

Edition sept 2018

(3)

JAVA – BASES DU LANGAGE

Les variables

Déclaration

Une variable est un espace mémoire qui peut recevoir une valeur.

Les variables peuvent être déclarées de différentes manières : selon le type de déclaration, on aura un type de variable particulier avec une durée de vie et une visibilité particulière.

4 types de variables Ø Variables locales

Les variables déclarées dans des fonctions sont des variables locales.

Leur durée de vie et leur visibilité est limitée au bloc dans lequel elles ont été déclarées.

En général, il s’agit d’une fonction. On peut aussi les déclarer dans une boucle for.

Ø Paramètres formels

Les variables déclarées en paramètre d’une fonction sont des paramètres formels.

Ils sont instanciés à chaque appel de la fonction.

Ø Variables d’instance = attributs ou champs

Les variables d’instance sont déclarées en attribut dans une classe. Elles seront instanciées avec l’instanciation de l’objet. Elles sont accessibles par le nom de l’objet qui les instancie. Elles existent en autant d’exemplaires qu’il y a d’objets instanciés. Une variable d’instance existe tant que l’instance existe.

Ø Variables de classe (mot clé « static »)

Les variables de classe sont déclarées en attribut dans une classe comme les variables d’instance, mais on y ajoute le mot clé « static » Elles sont accessibles par le nom de la classe. Elles n’existent qu’en un seul exemplaire. Une variable de classe existe pendant toute la durée de vie de l’application.

L’accès aux variables (et aux fonctions)

Les variables (et les fonctions) peuvent être « private », « protected », « public » ou sans caractéristiques d’accès.

• Les variables (et les fonctions) « public » sont accessibles par tout le monde de partout.

• Les variables (et les fonctions) « private » sont accessibles uniquement dans le code de la classe qui les contient.

• Les variables (et les fonctions) sans caractéristiques sont accessibles par tout le monde dans le package. La notion de package sera abordée plus précisément dans le chapitre « base de la programmation objet – suite ».

(4)

• Les variables (et les fonctions) « protected » sont accessibles uniquement dans le code de la classe qui les contient et dans le code de ses sous-classes (ses enfants). La notion de sous- classe et de variables protected sera abordée plus précisément dans le chapitre « héritage ».

Exemple

public class Personne{

private String nom;

---à nom : variable d’instance=attribut private String prenom; ---à idem private int anneeNaissance; à idem

public Personne(String nom, String prenom, int anneeNaissance) {

---à nom, prenom, anneeNaissance : 3 paramètres formels this.nom=nom;

---àthis.nom : variable d’instance, nom : parametre formel

this.prenom=prenom; ---à idem

this.anneeNaissance=anneeNaissance; ---à idem }

public String toChar(){

return nom+" "+prenom+" "+anneeNaissance;

---à nom, prenom, anneeNaissance : 3 Variables d’instances }

}

public class Main {

public static void main (String args[]) { ---à args : 1 paramètre formel

Personne[] monTab;

--à monTab: variable locale

monTab = new Personne[5];

monTab[0]=new Personne("toto3", "lolo", 1995);

monTab[1]=new Personne("tata", "lala", 1996);

monTab[2]=new Personne("titi", "lili", 1997);

monTab[3]=new Personne("tutu", "lulu", 1996);

monTab[4]=new Personne("toutou", "loulou", 1995);

for(int i=0 ; i<monTab.length; i++) { --à i: variable locale

System.out.println("tab["+i+"]="+monTab[i].toChar() );

} }

}

(5)

Nom

Règles de formation

• Commence par une lettre

• Constituée d’autant de lettres, chiffres ou ‘_’ qu’on veut

• Majuscules et minuscules sont distinguées.

• Un nom de variable ne doit pas reprendre un mot-clé du langage.

Usage

Le nom d’une variable est en minuscule. On met des majuscules à chaque nouvelle partie signifiante dans le nom de la variable : « maVariable ». C’est le camelCase.

Les 4 types de base (types primitifs ou types natifs) Numérique : byte, short, int, long

byte [-128, +128], short [-32768, +32767], int [-2 147 483 648, 2 147 483 647], long : encore plus grand.

byte [1 octet], short [2 octets], int [4 octets], long [8 octets]

Décimaux : float, double

float [1.4 E -45, 3.4.. E +38]; double [4,9 E -324, 1,79.. E 308]

float [4 octets], double [8 octets]

caractère : char char : 2 octets.

128 premiers caractères : ASCII. Jusqu’à 256 : alphabet latin accentué. Le reste : autres alphabets.

\t: tabulation, \b: backspace, \n: saut de ligne, \r: retour chariot, \’: quote, \”: double quote, \\:

antislash.

\uXXXX : X en hexa (0 à EF): code sur 2 octets.

booléen : boolean

boolean : vaut true ou false, et rien d’autre !.

Pointeur

Pas de pointeur en java !

Pas de pointeurs explicites mais des pointeurs implicites (des références) : des objets, des tableaux, des chaines de caractères.

Pas d’arithmétique de pointeurs (indirection, addition, soustraction, etc.).

Valeur par défaut

Toutes les variables d’instance (les attributs) valent 0 par défaut (false pour les booléens).

Par contre, les variables locales doivent être initialisées.

(6)

Valeurs littérales 10 // int par défaut

short s=10 ; // ce sera bien un short

10L //10 est considéré comme un long. On peut mettre l ou L.

0x0C // hexa : on commence par 0x, puis 0C en hexa = 12 014 // octal : on commence par 0, puis 14 en octal = 12 3.45 // double par défaut

float=3.45 : c’est bien un float

3.45f // casté en float. On peut mettre F, ou d pour double ou D.

x=3.45e3 // double par défaut. Vaut 3.45 *1000 (10 puissance 3)

Conversion : « cast » Deux techniques :

• F, F, l, L, etc. en fin de valeur littérale,

• (type) devant une valeur ou une variable Principes

Les entiers se transforment tous en réels.

Un « petit » peut passer dans un « grand » mais pas le contraire sans risque de perte d’informations.

Exemple

Int a=1, b=2 ;

Float c=a/2 ; // c vaut 0 car c’est une

Les constantes : final

Une variable est une variable dont on ne peut pas modifier la valeur.

Elle est déclarée en la précédant du mot clé : « final ».

final double PI=3.14 ;

Par convention, le nom des constantes est en majuscules.

En général, les constantes sont des variables de classes.

Les opérateurs

Classiques : +, - , /, *, %, (, ), ==, !=, <, <=, >, >=

La division est entière si les termes sont entiers, réelle sinon.

Exemple

public class TestVar{

public static void main (String args[]) {

(7)

// les variables locales doivent être initialisées avant d'être utilisées

final float PI=3.14f ; int n = 1;

float x ; char c ; boolean b ; x = 2*PI + n ; c='A';

b=true ;

System.out.println("PI = "+PI);

System.out.println("n = "+n);

System.out.println("x = "+x);

System.out.println("c = "+c);

System.out.println("b = "+b);

if(b) System.out.println("b = "+!b);

if(c=='A') System.out.println("c = 'A' : "+c);

else System.out.println("c != 'A' "+c);

int aa=1, bb=2;

float cc=aa/bb; // division entière System.out.println("cc : "+cc);

cc=aa/(float)bb; // division réelle System.out.println("cc : "+cc);

} }

(8)

Les tableaux

Déclaration et instanciation Déclaration

int[] monTab ; // déclaration d’une variable sans instanciation ou

int monTab[] ; // déclaration d’une variable sans instanciation

Attention, on ne peut pas écrire : int monTab[3] ;

type[] définit un type tableau en tant que classe la taille est variable. Accesible par le « .length ».

Par défaut : null.

Instanciation

monTab=new int[3] ; // instanciation de la variable ou bien

int [] monTab={12, 18, 9} ; // déclaration et instanciation Instance partagée : notion de référence

int[] t, monTab={12, 18, 9} ;

t=montab ; // si on modifie t ça modifie monTab

Utilisation Exemple 1

montTab[0]=12 ; montTab[1]=18 ; montTab[2]=19 ;

for(int i=0 ; i<monTab.length -1; i++) { System.out.println("tab[“+i+”]=”+tab[i]);

} Exemple 2

/**

* Déclaration de la classe principale de l’application * Programme pour tester l’usage des tableaux

*/

public class Tableau{

/** main : Fonction d’entrée dans toute application java */

public static void main (String args[]) {

(9)

/* déclaration du tableau */

int[] monTab;

/* création du tableau */

montTab=new int[args.length];

/* intialisation du tableau */

for (int i=0 ; i<=args.length; i++) { monTab[i]=Integer.parseInt(args[i]);

}

System.out.println();

/* affichage du tableau */

for(int i=0 ; i<monTab.length; i++) {

System.out.println("tab["+i+"]="monTab[i]);

} } }

Tableau à dimension > 1

int[][] matrice ; // déclaration d’une var. sans instanciation matrice=new int[3][2] ; // instanciation de la variable

int[][] matrice ={{12, 18, 9}, {8, 20, 1}, {2, 8, 6}} ; //

déclaration et instanciation

Taille du tableau : tab.length

tab.length donne le nombre d’éléments du tableau.

En cas de dépassement, on obtient une erreur : ArrayIndexOutOfBoundException

matrice.length donne le nombre de lignes de la matrice.

matrice[0].length donne le nombre de colonnes de la première ligne de la matrice.

En cas de dépassement, on obtient une erreur : ArrayIndexOutOfBoundException

Méthodes pour les tableaux API

Classe : java.util.Arrays

https://docs.oracle.com/javase/10/docs/api/java/util/Arrays.html

Toutes les méthodes sont listées. Si on clique dessus, on obtient le détail du fonctionnement de la méthode.

Quelques méthodes remarquables

length : taille du tableau

sort : trier un tableau

binarySearch : rechercher dans un tableau trié

(10)

toString : tranformer le tableau en chaîne de caractères, entre crochets

deepToString : toString pour tableau à dimension > 1

copyOf : copier un tableau dans un autre (ou lui-même), en modifiant sa taille si on le souhaite. Permet donc de redimensionner un tableau.

copyOfRange : copier une partie d’un tableau dans un autre (ou lui-même). Permet donc de redimensionner un tableau.

equals : comparer les contenus deux tableaux.

deepEquals : Equals pour tableau à dimension > 1

fill : remplir toutes les cases d’un tableau avec la même valeur.

Usages

A noter que les méthodes sont presque toutes « static ».

On écrira donc par exemple : Arrays.sort(monTab);

Ou encore

Arrays.equals(tab1, tab2); // comparaison des contenus.

Attention, on peut aussi écrire

tab1.equals(tab2); // compare les référence ó tab1 == tab2

le equals vient alors de la classe parente : ici « Object » qui propose equals() mais aussi toString() qui ne sont pas des méthode « static »

(11)

Les chaînes

Déclaration et instanciation Déclaration : classe String

String ch ; // déclaration d’une chaîne sans instanciation String : classe.

Taille : variable.

Par défaut : null.

Instanciation

String ch1="Bonjour"; // déclaration et instanciation ou bien

String ch2=new String("Bonjour"); déclaration et instanciation ou bien

ch1= "Au revoir " ; instanciation seule La valeur d’une chaîne n’est pas modifiable.

Toute modification est en réalité une nouvelle instanciation.

Instance partagée : notion de référence String ch, ch1="Bonjour";

ch=ch1 ; Accès à un caractère

Attention : on ne peut pas écrire ch[0] !!!

String ch="Bonjour";

char c = ch.charAt(0) ;

Exemple /**

* Déclaration de la classe principale de l’application * Programme pour tester l’usage des chaînes

*/

public class TestString{

/** main : Fonction d’entrée dans toute application java */

public static void main (String args[]) {

/* déclaration et instanciation des string */

String ch1="Bonjour";

String ch2=new String("l'IPI");

System.out.println(ch1);

System.out.println(ch2);

System.out.println(ch1 + ch2);

ch2="j'ai dit 2 fois \"bonjour l'IPI\"";

System.out.println(ch2);

(12)

String ch3 ;

ch3= "Au revoir " ;

System.out.println(ch3.toUperCase();

System.out.println(toUperCase("test " );

} }

Méthodes pour les chaînes API

Classe : java.lang.String

https://docs.oracle.com/javase/10/docs/api/java/lang/String.html

Toutes les méthodes sont listées. Si on clique dessus, on obtient le détail du fonctionnement de la méthode.

Quelques méthodes remarquables

• + : opérateur de concaténation

concat : concaténer deux chaînes

length : longueur de la chaîne

charAt : extraction d’un caractère (le premier en 0)

indexOf : renvoie la position de la première occurrence d’un caractère

substring : extraction d’un morceau de chaîne (debut et fin en paramètre)

equals : comparer deux chaînes, identique ou pas

compareTo : comparer deux chaînes. 0 si identique, >0 si plus grand, <0 si plus petit

toUpperCase : passer en majuscules

toLowerCase : passer en majuscules

concat : concaténer deux chaînes

replace : remplacer un caractère par un autre partout dans la chaîne

replaceAll : remplacer une chaîne par une autre partout dans la chaîne

replaceFirst : remplacer la première occurrence d’une string par une autre

trim : supprimer les espaces de début et de fin

split : découper une chaîne avec une expression régulière Usages

A noter que les méthodes ne sont en général pas « static ».

On écrira donc par exemple :

ch1.equals(ch2); // comparaison des contenus.

(13)

« equals » est une méthode de la classe String. ch1.equals(ch2) veut dire qu’à partir de l’objet

« ch1» de la classe String, on accède à la méthode « equals ». Cette méthode prend une autre chaîne en paramètre et compare le contenu des deux chaînes pour renvoyer vrai ou faux si elles sont identiques ou pas.

(14)

Les structures : vers la P.O.O.

Structure = Classe

Il n’y a pas de structure en Java. Ce sont les classes de la programmation objet qui gère ça.

Pour déclarer une structure, on va donc déclarer une classe.

On va montrer dans ce paragraphe une façon de coder qui fait « comme si » on avait une structure, pour se rapprocher le plus possible d’une logique algorithmique.

On montrera ensuite l’évolution de cette façon de faire vers de la programmation objet.

Déclaration et instanciation

Déclaration : classe StructPersonnne

On travaille sur une structure à 3 champs (=attributs) : nom, mail et année de naissance.

public class StructPersonne{

public String nom;

public String mail;

public int anneeNaissance;

}// déclaration d’une chaîne sans instanciation La structure est une classe.

Elle sera déclarée dans un fichier séparé : StructPersonne.java.

On ajoute « public » devant le mot clé « class » : ça signifie qu’on pourra s’en servir.

Tous les attributs sont « public » : ça signifie qu’on pourra s’en servir comme on veut.

Instanciation

StructPersonne unePersonne=new StructPersonne();

Cette écriture permet de créer une variable (un objet) appelée « une personne ». On pourra maintenant donner des valeurs pour chacun des attributs.

Instance partagée : notion de référence StructPersonne p2

p2=unePersonne ;

Avec cette écriture, p2 et unePersonne font référence à la même personne concrète.

Utilisation d’une structure dans le Main /**

* Déclaration de la classe principale de l’application * Programme pour tester l’usage des structures

*/

public class Main{

{

public static void main (String args[]) {

StructPersonne unePersonne=new StructPersonne();

unePersonne.nom="toto1";

unePersonne.prenom="toto@truc.fr";

(15)

System.out.println("unePersonne =" +unePersonne.nom+" "

+unePersonne.prenom+" "+unePersonne.anneeNaissance );

StructPersonne p2;

p2=unePersonne; // p2 et unePersonne sont des références

p2.anneeNaissance=2000; // ça modifie p2 et unePersonne System.out.println("p2 =" +p2.nom+" "

+p2.prenom+" "+p2.anneeNaissance );

System.out.println("unePersonne =" +unePersonne.nom+" "

+unePersonne.prenom+" "+unePersonne.anneeNaissance );

} }

Tableau de structures

Déclaration : classe StructPersonnne

StructPersonne[] monTab;

monTab = new StructPersonne[5];

ou

StructPersonne[] monTab = new StructPersonne[5];

Syntaxe

MonType[] monTab = new MonType[5];

Utilisation d’un tableau de structures dans le Main Ø On se dote d’une fonction newPersonne

Elle permet de créer une personne à partir de la valeur de ses attributs.

Utilisation de la fonction :

StructPersonne personne =newPersonne("toto1", "toto@truc.fr", 1995);

Ø Déclaration et remplissage du tableau.

On remplit en utilisant la fonction.

StructPersonne[] monTab = new StructPersonne[5];

monTab[0]=newPersonne("toto1", "toto@truc.fr", 1995);

Ø Remarques syntaxique

Les fonctions de la classe Main (qui contient la fonction « main ») sont toutes « static ».

Pour le moment, la « class » et les fonctions sont « public ».

Ø Exemple complet public class Main {

public static StructPersonne newPersonne(String nom, String prenom, int anneeNaissance) {

StructPersonne unePersonne=new StructPersonne();

(16)

unePersonne.nom=nom;

unePersonne.prenom=prenom;

unePersonne.anneeNaissance=anneeNaissance;

return unePersonne;

}

public static void main (String args[]) {

StructPersonne[] monTab;

monTab = new StructPersonne[5];

monTab[0]=newPersonne("toto1", "toto@truc.fr", 1995);

monTab[1]=newPersonne("tata", "tata@truc.fr", 1996);

monTab[2]=newPersonne("titi", "titi@truc.fr", 1997);

monTab[3]=newPersonne("tutu", "tutu@truc.fr", 1996);

monTab[4]=newPersonne("toutou", "toutou@truc.fr", 1995);

for(int i=0 ; i<monTab.length; i++) { System.out.println("tab["+i+"]="

+monTab[i].nom+" "

+monTab[i].prenom+" "

+monTab[i].anneeNaissance );

} }

}

Vers la P.O.O : notion de constructeur

On va déplacer la fonction newPersonne dans la classe Personne Ø Constructeur

« newPersonne » aura forcément le nom de la classe. Ici : Personne(…) Ce type de fonction s’appelle « constructeur ».

On peut lui passer des paramètres. Ici :

public Personne(String nom, String prenom, int anneeNaissance)

Ø This

Le mot clé « this » permet en quelque sorte de créer une nouvelle personne : Personne unePersonne=this;

Ø Code

On obtient donc la classe suivante : public class Personne{

public String nom;

public String prenom;

public int anneeNaissance;

public Personne(String nom, String prenom, int anneeNaissance) {

Personne unePersonne=this;

(17)

unePersonne.nom=nom;

unePersonne.prenom=prenom;

unePersonne.anneeNaissance=anneeNaissance;

} }

Utilisation dans le Main

Le main est simplifié : on n’y trouve plus la fonction newPersonne.

Par contre, l’utilisation du constructeur se fait avec le mot clé « new » :

monTab[0]=new Personne("totoo", "lolo", 1995);

Ø Exemple complet public class Main {

public static void main (String args[]) {

Personne[] monTab;

monTab = new Personne[5];

monTab[0]=new Personne("totoo", "lolo", 1995);

monTab[1]=new Personne("tata", "lala", 1996);

monTab[2]=new Personne("titi", "lili", 1997);

monTab[3]=new Personne("tutu", "lulu", 1996);

monTab[4]=new Personne("toutou", "loulou", 1995);

for(int i=0 ; i<monTab.length; i++) { System.out.println("tab["+i+"]="

+monTab[i].nom+" "

+monTab[i].prenom+" "

+monTab[i].anneeNaissance );

} }

}

P.O.O

La classe Personne Ø code

public class Personne{

private String nom;

private String prenom;

private int anneeNaissance;

public Personne(String nom, String prenom, int anneeNaissance) {

this.nom=nom;

this.prenom=prenom;

this.anneeNaissance=anneeNaissance;

}

public String toChar(){

(18)

return nom+" "+prenom+" "+anneeNaissance;

} }

Ø Explications

Désormais les attributs sont private : principe d’encapsulation.

On a ajouté une fonction dans la classe : toChar() qui permet de retourner une chaine de caractères avec les information d’une personne.

La fonction toChar a entrée une personne et en sortie les infos de la personne.

Il n’y a pas de paramètres car la personne sera fourni avec l’usage de la fonction : on écrira : System.out.println( unePersonne.toChar() )

La classe Main Ø code

public class Main {

public static void main (String args[]) {

Personne[] monTab;

monTab = new Personne[5];

monTab[0]=new Personne("toto3", "lolo", 1995);

monTab[1]=new Personne("tata", "lala", 1996);

monTab[2]=new Personne("titi", "lili", 1997);

monTab[3]=new Personne("tutu", "lulu", 1996);

monTab[4]=new Personne("toutou", "loulou", 1995);

for(int i=0 ; i<monTab.length; i++) {

System.out.println("tab["+i+"]="+monTab[i].toChar() );

} }

}

Ø Explications

Dans la classe Main, on n’utilise plus directement les attributs de la classe Personne.

Etant devenus « private », ils sont inaccessibles. D’où l’écriture de la fonction toChar().

(19)

Contrôle de la séquence

Tests if

4 syntaxes possibles :

if (condition) une instruction

if (condition){

des instructions }

if (condition) ...

else

une instruction

if (condition) ...

else{

des instructions }

Le bon usage : toujours mettre des accolades elseif

Le elsief (tout attaché) n'existe pas mais on peut mettre une instruction unique if dans un else, ce qui donne un équivalent d'un elseif tout attaché.

Le bon usage : if (condition){

des instructions }

else if {

des instructions }

else if {

des instructions }

else {

des instructions }

(20)

switch

Le switch est équivalent à un elseif mais on n’est obligé de faire une comparaison d’égalité sur une seule variable. Il faut aussi faire un break pour sortir quand on passe par une branche du switch.

Le bon usage :

switch (expression) { case valeur1:

des instructions break;

case valeur 2:

des instructions break;

case valeur 3:

des instructions break;

default :

des instructions }

Boucles while

Le bon usage :

while(condition){

des instructions }

do while

Le bon usage : do{

des instructions }while(condition);

for

Le bon usage :

for(int i=0 ;i<n ; i++){

des instructions }

Ou:

for(int i=0 ; i<tab.length; i++) { des instructions

}

for sans indice int i=0;

for(int elt : monTab){

System.out.println("tab["+i++ +"]="+ elt);

}

(21)

Débranchement break et continue

le break permet de sortir de la boucle ou il se trouve, ou de sortir de la boucle auquel il fait référence.

Le continue permet d’aller à la fin de la boucle ou il se trouve, ou d’aller à la fin de la boucle auquel il fait référence.

Le bon usage 1 : sortie d’une boucle for(int i=0 ;i<n ; i++){

des instructions if (condition){

des instructions break; // ou continue }

des instructions }

Le bon usage 2 : sortie de boucles imbriquées – boucle avec étiquettes maboucle : while(condition){

des instructions

for(int i=0 ;i<n ; i++){

des instructions if (condition){

des instructions

break maboucle; // ou continue }

des instructions }

des instructions }

return

Le return permet de quitter la fonction (méthode) dans lequel il est utilisé.

Il permet aussi de renvoyer une valeur sur la sortie standard de la fonction (méthode) . goto

Pas de goto en java ! Le principal usage du goto, à savoir la sortie de boucles imbriquées, est pris en charge par les boucles avec étiquette et les débranchements de boucle avec étiquette.

(22)

Fonctions

Remarques préliminaires

Les fonctions sont toujours déclarées dans les classes. Dans un premier temps, on ne voit que la déclaration des fonctions « static » qui sont accessibles par le nom de leur classe. Les fonctions non « static » sont seulement utilisées (toUpperCase par exemple).

Exemple /**

* Déclaration de la classe principale de l’application * Programme pour tester l’usage des tableaux

*

* @author : INSIA */

public class Tableau2{

/** main : Fonction d’entrée dans toute application java */

public static void main (String args[]) {

/* déclaration du tableau */

int[] monTab;

/* création du tableau */

monTab=new int[args.length];

/* intialisation du tableau */

for (int i=0 ; i<args.length; i++) { monTab[i]=Integer.parseInt(args[i]);

}

System.out.println();

/* affichage du tableau */

int res=afficherTableau(monTab);

// on peut aussi écrire : Tableau.afficherTableau System.out.println

("Le tableau contient "+res+" elements");

} /**

* afficherTableau : Fonction d’affichage d’un tableau *

* @param Entrée : tab : le tableau à afficher * @param Sortie : affichage du tableau

* @param Return : la taille du tableau */

private static int afficherTableau (int[] tab){

System.out.println("Affichage du tableau :");

for(int i=0 ; i<tab.length; i++) {

System.out.println("tab["+i+"]="+tab[i]);

}

return tab.length;

}

(23)

}

Syntaxe

Une fonction est composée d’une en-tête (ou signature) et d’un corps.

La syntaxe est similaire à celle du langage C :

type nomFonction (type var1, type var2…) { instructions

}

Qualificateurs

« private » ajouté devant la signature rend la fonction accessible uniquement par les fonctions de sa classe (Tableau). On pourrait aussi mettre « public ».

« static » ajouté devant la signature rend la fonction accessible directement sans avoir besoin d’objet.

Usages des fonctions (ou méthodes) :

Méthodes de classe : définie avec un « static »

Dans ce cas, le nom de la méthode est préfixé par sa classe d’appartenance, sauf si l’appel de la méthode se fait dans la classe de définition de la méthode.

L’usage des méthodes de classes est équivalent à celui des fonctions de la programmation classique (pas objet).

Ø Exemples

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

resultat=Integer.parseInt(args[i-1]) ; monTab[i]=Integer.parseInt(args[i]);

int res=afficherTableau(monTab);

// ou alors : int res= Tableau.afficherTableau(monTab);

Ø Explications

La méthode « println » est définie dans la classe System du package java.lang (importé par défaut). Elle à une String en paramètre.

La méthode « parseInt » est définie dans la classe Integer du package java.lang (importé par défaut). Elle a une String en paramètre et elle renvoie un entier.

La méthode « afficherTableau » est définie dans la classe Tableau. Elle a un tableau en paramètre et elle renvoie un entier.

(24)

Méthodes d’instance : définie sans “static”

Dans ce cas, le nom de la méthode est préfixée par l’objet (la variable) auquel la méthode va s’appliquer. C’est un usage caractéristique de la programmation objet.

Ø Exemples

• if (args[i].equals("-")) {

• System.out.println(ch3.toUpperCase());

Ø Explications

La méthode “equals” s’applique à “args[i]” qui est une String. Cette méthode est donc définie dans la classe String du package java.lang (importé par défaut).. Elle reçoit une String en entrée : ici "-".

La méthode « toUpperCase() » s’applique à ch3 qui est une String. Cette méthode est donc définie dans la classe String du package java.lang (importé par défaut). Elle n’a pas de paramètres.

Mode de passage des paramètres

Le return permet de renvoyer des variables de type simple et des références vers des tableaux, des chaines, des objets. int[] maFonction(…) renvoie un tableau d’entiers.

Les variables de type simple sont forcément passées en entrée et ne peuvent pas être modifiée.

C’est un passage par valeur : c’est en réalité la valeur de la variable qu’on transmet.

Les références permettent la modification du référé dans la fonction. Toutes les références sont donc potentiellement en entrée et en sortie. La valeur de la référence ne sera par contre pas modifié.

On verra aussi que java gère un deuxième canal de sortie : la sortie en erreur (throws).

Récursivité

Le java permet d’écrire des fonctions récursives.

(25)

Saisie et affichage

https://docs.oracle.com/javase/10/docs/api/java/lang/System.html

Affichage

Affichage non formaté : print et println System.out.println(“Bonjour”);

« out » est une variable de classe de la classe System. Cette variable est de classe PrintStream.

La méthode println est définie dans la classe PrintStream.

println passe à la ligne.

print ne passe pas à la ligne.

Affichage formaté : printf

System.out.printf(“Bonjour %d\n”, i);

C’est l’équivalent du C.

%3d permet de formater un entier sur 3 caractères

%6.2f permet de formater un float sur 6 caractères avec 2 après la virgule

%g permet de formater un nombre « au mieux » automatiquement.

%-10s permet de formater une chaine de caractères sur 10 caractères (ça débordera si nécessaire) en callant de texte à droite.

Etc.

Saisie

Lecture non formatée (lire une chaîne jusqu’au retour chariot) String nom=System.console().readLine();

System.out.println(nom);

• On crée un objet Console (package java.io) avec la méthode console() de la classe System (package java.lang).

• A partir de l’objet Console, on accède à la méthode readline() qui permet de lire un chaîne de caractère jusqu’au retour chariot et qui retourne donc un objet chaîne de caractère.

• On pourra ensuite caster la chaîne lue.

Lecture typée

Ce mode de lecture sera abordé avec la programmation objet.

(26)

Exception

Le problème

Soit la fonction « inverse » qui renvoie l’inverse d’un réel.

En C, sans gestion d’erreur, la fonction s’écrit : double inverse(double a) {

return 1/a ; }

L’usage de la fonction pourra être : res = inverse(5);

Le problème est que si on passe “0” à cette fonction, le programme va « planter ».

Si on veut gérer le cas d’erreur, on devra écrire int inverse(double a, double * res) {

if (a==0) return 0 ; *res=1/a;

return 1;

}

L’usage de la fonction devra alors être : int ok;

double res;

ok = inverse(5, &res);

if (ok==0) printf(“ division par 0 impossible” ;

Le code est assez lourd et surtout on a perdu l’usage classique de la fonction dans une expression, du type : 4*inverse(3)

La solution : un canal dédié aux exceptions : throws et throw

La solution consiste à ce que le compilateur gère un deuxième canal de retour dédié aux exceptions.

Dans le code, le retour par ce deuxième canal se fait par le mot-clé « throw » : c’est l’équivalent d’un « return ».

Dans l’en-tête, le type de retour par ce deuxième canal se fait par le mot-clé « throws ».

En java, la fonction inverse s’écrira :

double inverse(double a) throws Exception {

if (a==0) throw new Exception("division par 0 impossible");

return 1/a;

}

(27)

L’usage de la fonction devra alors être : try{

res=inverse(5) ; }

catch(Exception e) {

System.out.println(e.getMessage());

}

Le code est alourdi par la présence du try.

Mais le premier avantage est que l’appel de la fonction est classique : inverse(5). On peut toujours intégrer la fonction dans une expression du type : 4*inverse(5).

Le deuxième avantage vient ensuite de la gestion des exceptions par le compilateur et du fait qu’on peut choisir le moment où on traite l’exception car celle-ci remonte la pile des fonctions appelantes.

On peut choisir notre message d’exception et le traiter comme on le souhaite. On le récupère avec le e.getMessage().

La récupération d’exception : 1 try … N catch … 1 finally Principes

• TRY : Le code à risque est placé dans un bloc « try ».

• CATCH : Le bloc « try » est suivi par un ou plusieurs blocs « catch » qui pourront prendre en compte différents types d’exception. Si aucune exception ne correspond, alors le moteur java remonte à la méthode appelante pour trouver une exception adaptée.

• FINALLY : Les blocs « catch » peuvent être suivi (facultatif) par un bloc « finally » qui sera exécuté dans tous les cas (sauf si le bloc « catch » fait quitter la méthode par un System.exit).

L’intérêt du bloc « finally » se justifie quand l’exception n’est pas traitée au niveau où elle est décelée.

Syntaxe try{

instructions ; }

catch(IOException e) { instructions ;

}

catch(Exception e) { instructions ; }

finally{

instructions ; }

Remaques

S’il y a plusieurs catch, seul le premier qui « matche » est traitée. C’est pourquoi on doit commencer par mettre les exceptions dérivées avant les exceptions de base.

En effet, une exception est un objet qui va se substituer à la variable du CATCH. Par exemple, si le try génère un objet exception de la classe IOException, on passera dans le catch IOException. Mais si le try génère un objet exception de la classe ArithmeticException, celui-

(28)

ci peut se substituer (selon le principe de substitution) au « e » du « catch(Exception e » car une ArithmeticException est une Exception.

Les erreurs les plus fréquentes

Division par 0 ArithmeticException

Référence nulle NullPointerException

Type illégal ClassCastException

Tableau de taille négative NegativeArraySizeException Dépassement de la limite d’un tableau ArrayIndexOutOfBoundsException

Format non valide NumberFormatException

Exemple de simple try catch Ø Code

public class TryCatch{

public static void main (String args[]) { int arg1, arg2=0;

try {

arg1=Integer.parseInt(args[0]);

}

catch(Exception e) { arg1=0;

}

System.out.println("arg1 : "+arg1);

try {

arg2=Integer.parseInt(args[1]);

}

catch(Exception e) {

System.out.println("exception levee : "+ e);

return;

}

System.out.println("arg2 : "+arg2);

} }

Ø Résultats

C:\ >java TryCatch arg1 : 0

exception levee : java.lang.ArrayIndexOutOfBoundsException: 1 C:\ >java TryCatch 1 1.2

arg1 : 1

exception levee : java.lang.NumberFormatException: For input string: "1.2"

(29)

Paquetage (package)

Présentation

Un paquetage est une bibliothèque de classes organisée de façon hiérarchique.

Le nom d’un paquetage est le nom du répertoire dans lequel se trouve la classe.

Les paquetages peuvent être rassemblés dans des archives « .zip » ou « .rar ».

Hiérarchie des paquetages standards java

java

lang util io applet awt

java.lang contient les classes fondamentales : String, Math, etc. Elle est importée par défaut.

Java.util contient les classes relatives aux collections, à de la gestion de dates, etc. Elle n’est pas importée par défaut. Il faut l’importer par exemple quand on utilise des Arrays.

java.io contient les classes relatives aux entrées-sorties javax

javax est une autre racine de paquetage qui contient des éléments plus récent et particulièrement la bibliothèque graphique Swing qui tend à remplacer la bibliothèque AWT.

Syntaxe

Inclusion de la classe dans un paquetage package nomPaquetage ; Importation d’une classe

import nomPaquetage.nomClasse;

Importation d’un paquetage complet import nomPaquetage.* ;

// à éviter car c’est peu informatif !

Exemples Arrays

/* Importation de la classe Arrays pour faire Arrays.sort() */

import java.util.Arrays;

Calendar, GregorianCalendar

(30)

import java.util.Calendar;

import java.util.GregorianCalendar;

...

// dans une classe : public int getAge(){

return new GregorianCalendar().get(Calendar.YEAR) - anneeNaissance;

Deprecated

A noter que certaines classes ou méthodes peuvent être devenues « deprecated ». Dans ce cas, il vaut mieux éviter de les utiliser, même si elles marchent encore, pour mieux assurer la pérénité du code.

CLASSPATH

La variable d’environnement CLASSPATH indique à la JVM où trouver les classes et bibliothèques de classes dont elle a besoin.

C’est l’équivalent du Path des OS.

(31)

JAR

Présentation

jar.exe est un utilitaire qui permet de compresser ses dossiers et package de fichiers java (de classes).

Il produit une archive .jar. C’est une archive qu’on peut ouvrir comme un zip par exemple.

JAR exécutable

L’intérêt de l’outils de de permettre de fabriquer des archives qui pourront être utilisées directement comme des programmes.

Fabrication d’un JAR En console

En console, on utilise l’utilitaire jar.exe.

Il faut créer un fichier de configuration particulier appelé : MANIFEST.MF Avec un IDE : Eclipse

Un IDE permet plus facilement de fabriquer des JAR.

Référence

https://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html

(32)

TP

1) Coder la classe Tableau (dans le poly). Compiler. Exécuter.

2) Coder la classe TestString (dans le poly). Compiler. Exécuter.

3) Coder les classes d’utilisation d’une structure dans le main (dans le poly, version avant la POO). Compiler. Exécuter.

4) Coder les classes d’utilisation d’un tableau de structures dans le main (dans le poly, version avant la POO). Mettez l’affichage dans une fonction. Compiler. Exécuter. Générer la documentation avec javadoc.

5) Coder un programme qui résout une équation du premier degré en passant les paramètres en ligne de commande. Le programme séparera radicalement le calcul des résultats de l’affichage des résultats. On fera une version sans fonction et une version avec une fonction qui affiche les résultats à partir du nombre de solutions et des solutions calculées. Le principe de résolution est le suivant : l’équation à la forme aX+b=0. On fournit a et b pour résoudre l’équation. Si (a,b)=(0,0), il y a une infinité de solutions. Si (a,b)=(0, !=0), il n’y a pas de solution. Si a !=0, la solution est –b/a.

6) Ecrire un programme qui code le tri d’un tableau en utilisant la méthode du tri à bulle. Le programme récupèrera les données en ligne de commande, les affichera sur une seule ligne, puis les triera et les réaffichera sur une seule ligne une fois le tri effectué.

7) Coder un programme qui tri un tableau d’au moins 5 entiers fournis en ligne de commande, le tri en ordre croissant. Le programme affiche le tableau initial sur une seule ligne, puis le tableau trié sur une seule ligne, crée une copie de ce tableau avec les 5 éléments en plus initialisé à 0 et affiche le tableau en ordre décroissant.

Pour cet exercice, vous pouvez vous intéresser aux fonctions de manipulation des tableaux (classe Arrays). Cherchez l’usage de la fonction « sort ».

8) Ecrire un programme qui récupère en ligne de commande une phrase dont les mots sont séparés par des espaces. Le programme devra afficher le nombre d’arguments (il doit valoir 1), la phrase complète et le nombre de mots de la phrase.

9) Reprendre des exercices d’algorithmique.

Références

Documents relatifs

Hybrid expansion of the Ben Harper audio signal based on structured N-term approximation; from top to bottom: original, tonal layer, transient layer, residual.. method produces

Nommer et énumérer (compter le nombre total) les différents types d'atomes présents dans les réactifs!. Nommer et énumérer (compter le nombre total) les différents types d'atomes

Les figures suivantes sont faites à main levée.. Coder chaque figure à l’aide des

The probably smarter way is an interpreter, with data structures that controls the behaviour: a sequence of read operations processes the input stream, and writes the resulting

En s'intéressant à ses angles et à ses diagonales, donner deux propriétés vérifiées par un rectangle, et qui ne sont pas toujours vraies pour n'importe quel parallélogramme..

Pour définir d’autres méthodes spécifiques aux polynômes du second degré, on crée la classe Poly2d héritant de la classe Poly. On surchargera la méthode __init__ de façon

[r]

Au fil de ce cours, nous aborderons également d’autres langages comme le XHTML ou le PhP lorsque cela justifié et afin que vous ayez une compréhension globale