À partir de maintenant, nous allons nous servir à nouveau de notre projet
Ville (celui que vous avez utilisé dans les premiers chapitres...).
Nous allons perfectionner un peu la gestion de nos objets
Ville et
Capitale... Comment ? Eh bien je vois bien une exception qui pourrait être créée... Et je suis sûr que certains petits malins se sont déjà amusés à créer des villes ou des capitales avec un nombres d'habitants négatif....
Je vous propose simplement de mettre en oeuvre une exception de notre cru, ceci afin de pouvoir interdire l'instanciation d'objet
Ville ou
Capitale ayant un nombre négatif d'habitants.
La procédure pour faire ce tour de force est un peu particulière :

- Nous devons créer une classe héritée de la classe Exception : appelons-la NombreHabitantException. Par convention, les exceptions ont un nom se terminant par Exception.
- Nous devons renvoyer l'exception levée à notre classe NombreHabitantException.
- Ensuite, gérer celle-ci dans notre classe NombreHabitantException.
Comment faire tout ça ?
Eh bien je vais vous apprendre encore deux autres mots clés !
Non, ne grimacez pas... Je vous assure que si vous en retenez un, vous allez retenir l'autre...
Le premier mot clé
throws
Ce mot clé permet de dire à une instruction Java (condition, déclaration de variable...) ou à une classe entière qu'une exception potentielle sera gérée par une classe -
souvent une classe personnalisée- mais ce peut être la classe
Exception elle-même. Ce mot clé est suivi du nom de la classe qui va gérer l'exception. Ceci a pour but de définir le type d'exception qui risque d'être générée par l'instruction, ou la classe qui précède le mot clé
throws.
Le deuxième mot clé
throw
Celui-ci permet d'instancier un objet dans la classe suivant l'instruction
throws. Cette instruction est suivie du mot clé
new ainsi que d'un objet cité avec
throws. En fait, il lance une exception, tout simplement.
Faites surtout bien attention à ne pas confondre ces deux mots clé.
Pour pouvoir mettre en pratique ce système, nous devons commencer par créer une classe qui va gérer nos exceptions. Celle-ci, je vous le rappelle, doit être héritée d'
Exception. Pour commencer, inutile de créer un constructeur, ce qui nous donnerait une classe
Erreur, héritée de
Exception, vide.
Comme ceci :
Code : Java | class NombreHabitantException extends Exception{
public NombreHabitantException(){
System.out.println("Vous essayez d'instancier une classe Ville avec un nombre d'habitants négatif !");
}
}
|
Reprenez votre projet avec vos classes
Ville,
Capitale et créez maintenant une classe
NombreHabitantException, comme je viens de le faire !
Maintenant, c'est dans le constructeur de nos objets que nous allons mettre une condition qui, si elle est remplie, lève une exception de type
NombreHabitantException.
En gros, nous devons dire à notre constructeur de ville : "
Si l'utilisateur crée une instance ville avec un nombre d'habitants négatif, créer un objet de type NombreHabitantException (hérité d'Exception).
Le constructeur d'initialisation de ville doit ressembler à ce qui suit, maintenant.
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | public Ville(String pNom, int pNbre, String pPays) throws NombreHabitantException
{
if(pNbre < 0)
throw new NombreHabitantException();
else
{
nbreInstance++;
nbreInstanceBis++;
nomVille = pNom;
nomPays = pPays;
nbreHabitant = pNbre;
this.setCategorie();
}
}
|
throws NombreHabitantException nous indique que si une erreur est capturée, celle-ci sera traitée en tant qu'objet de la classe
NombreHabitantException ! Ce qui, au final, nous renseigne sur le type de l'erreur en question.
throw new NombreHabitantException(); instancie la classe
NombreHabitantException si la condition
if(nbre < 0) est remplie.
Maintenant que vous avez fait cette petite modification, retournez dans votre classe
main, effacez son contenu, puis créez un objet
ville de votre choix !
Et à présent, vous devez voir une erreur persistante ; c'est tout à fait normal, ce qui doit vous donner ceci :
Ceci signifie qu'à partir de maintenant, dû aux changements dans le constructeur, vous devrez gérer les exceptions possibles sur cette instruction. Avec un bloc
try{} catch{}.
On dit aussi que votre constructeur est devenu une méthode à risque, et vous avez laissé le soin au développeur de gérer l'exception potentielle !
Donc, pour que l'erreur disparaisse, il nous faut entourer notre instanciation avec un bloc
try{...}catch{...}.
Comme ceci :
Vous pouvez constater que l'erreur a disparu et que notre code compile et s'exécute correctement.

Par contre, il faut que vous soyez préparés à une chose. Le code que j'ai utilisé ci-dessus fonctionne très bien, mais ce code :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12 | public class Sdz1 {
public static void main(String[] args)
{
try {
Ville v = new Ville("Rennes", 12000, "France");
} catch (NombreHabitantException e) {}
System.out.println(v.toString());
}
}
|
ne fonctionnera pas et pour appuyer mes dires, voici le témoignage de quelqu'un d'intègre :
Vous pouvez constater qu'Eclipse n'aime pas du tout notre code !
Pourquoi cela ?
Tout simplement car la déclaration de votre objet
Ville est faite dans un sous-bloc d'instructions, celui du bloc
try{}. Et rappelez-vous :
Une variable déclarée dans un bloc d'instructions n'existe que dans ce bloc d'instructions !
Donc, ici, notre objet
v, n'existe pas en dehors de l'instruction
try{}. Pour
pallier ce problème, il nous suffit de
déclarer notre objet en dehors du bloc try{} et de l'instancier à l'intérieur !
Nous pouvons faire ceci :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13 | public class Sdz1 {
public static void main(String[] args)
{
Ville v = null;
try {
v = new Ville("Rennes", 12000, "France");
} catch (NombreHabitantException e) {}
System.out.println(v.toString());
}
}
|
Et ce code nous donne :
Code : Console | Rennes est une ville de France, elle comporte : 12000 => elle est donc de catégorie : C |
Mais si nous déclarons une Ville avec un nombre d'habitants négatif pour tester notre exception ?
Avec ce code, par exemple :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13 | public class Sdz1 {
public static void main(String[] args)
{
Ville v = null;
try {
v = new Ville("Rennes", -12000, "France");
} catch (NombreHabitantException e) {}
System.out.println(v.toString());
}
}
|
Voici ce que nous obtenons :
Voyons ce qu'il s'est passé.
- Nous avons bien déclaré notre objet en dehors du bloc d'instructions.
- Au moment d'instancier celui-ci, une exception est levée ! L'instanciation échoue lamentablement !

- La clause catch{} est exécutée et notre objet NombreHabitantException est instancié. Écriture du message.
- Et lorsque nous arrivons sur l'instruction "System.out.println(v.toString());", notre objet est null !
- Une NullPointerException est levée !
Ce qui signifie que si notre instanciation a échoué dans notre bloc
try{}, le programme plantera !
Comment empêcher cela, alors ?
Vous allez voir, c'est très simple. Il suffit d'instancier un objet
Ville par défaut dans notre bloc
catch{}. Grâce à cela, si notre instanciation avec valeur échoue, on fait une instanciation par défaut qui, elle, n'est pas une méthode à risque !
Voyez plutôt :
Vous pouvez voir que l'exception est bien levée et que notre objet est instancié mais, surtout, que notre programme ne plante plus !
Maintenant que nous avons vu la création d'exception, il serait de bon ton que nous puissions avoir de plus amples renseignements concernant celle-ci.

Par exemple, il serait peut-être bon de réafficher le nombre d'habitants que l'objet a reçu...
Pour faire ceci, nous n'avons qu'à créer un deuxième constructeur dans notre classe
NombreHabitantException, qui prend un nombre d'habitants en paramètre. Un peu comme ça :
Code : Java | public NombreHabitantException(int nbre)
{
System.out.println("Instanciation avec un nombre d'habitants négatif");
System.out.println("\t => " + nbre);
}
|
Il vous suffit maintenant de définir cette construction de notre objet hérité d'
Exception dans votre classe
Ville. Comme ça :
Code : Java 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | public Ville(String pNom, int pNbre, String pPays) throws NombreHabitantException
{
if(pNbre < 0)
throw new NombreHabitantException(pNbre); // on appelle le nouveau constructeur
else
{
nbreInstance++;
nbreInstanceBis++;
nomVille = pNom;
nomPays = pPays;
nbreHabitant = pNbre;
this.setCategorie();
}
}
|
Et si vous exécutez le même code que précédemment, vous obtiendrez ceci :
C'est pas mal, avouez-le !

Mais vous devez savoir que l'objet passé en paramètre de la clause
catch a des méthodes héritées de la classe
Exception. Regardez :
Vous pouvez les utiliser si vous le voulez et surtout, si vous en avez l'utilité...
Nous utiliserons certaines de ces méthodes dans les prochains chapitres...
Ici, la méthode printStackTrace() permet de voir ou se situe l'exception dans notre code ! Elle vous informe sur le nom de la classe levant l'exception et le numéro de ligne ou se trouve le code l'ayant levée.
Je vais vous faire peur : ici, nous avons capturé une exception mais nous pouvons en capturer plusieurs...
