TPs Java 6 - Partie I

Quelques TPs pour apprendre Java 6, extraits de mon livre Java 6 Java Standard Edition (JSE) : Entraînez-vous et maîtrisez Java par la pratique

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

Introduction

Cet article vous propose quelques TPs de base pour pratiquer Java 6. Cette première partie se focalisera sur des points valables pour presque toutes les plateformes. Un minimum de connaissance théorique est impératif pour avancer, et l'usage de la javadoc 1.6 est nécessaire.

Des indices sont à chaque fois disponibles en fin de chapitre. Les solutions dans des chapitres à part.

1. Contrôle de flux

1.1. Énoncés

1. Dans une classe TestCalcul et une méthode main, créer une table de multiplication de 1x1 à 9x9 en employant en même temps au moins 2 styles de boucles différentes.

Image non disponible

2. En modifiant l'exemple précédent, créer une table de division de -9/9 à +9/9.

Image non disponible

3. Créer une classe Calculatrice comportant une méthode calcul(char operateur, double operande1, double operande2). L'opérateur peut être '+', '-', '*', '/'. Afficher dans la console le détail et le résultat de chaque opération.

Image non disponible

4. Transformer l'exemple précédent pour que la méthode calcul retourne la valeur du calcul au lieu de l'afficher dans la console.

1.2. Indices pour l'énoncé

1. Employer par exemple une boucle for avec une boucle while. Faire attention à la portée des variables et à bien réinitialiser les indices de boucle.

2. Prendre en compte la division par zéro et utiliser par exemple le mot-clé continue.

3. L'instruction System.out.printf sert à afficher dans la console une chaîne formatée, par exemple System.out.printf( "%2.2f+%2.2f\n", 3.5, 1.5) affichera 3.50+1.50. Vous pouvez également employer l'instruction System.out.println. Utiliser les possibilités du switch/case pour les différents cas.

4. Il vous faut retourner la valeur du calcul. L'affichage dans le console peut se faire dans la méthode principale (main) de test.

2. Exception

2.1. Énoncés

En partant de la classe Calculatrice (étape 4 de l'énoncé précédent).

1. Créer une exception CalculException. Utiliser cette exception dans la méthode calcul pour remonter les erreurs de calcul (division par zéro et opéra-teur inconnu). Dans votre méthode main de test, afficher simplement la stackTrace de l'exception (pile d'appels).

Image non disponible

2. Diviser la méthode calcul en deux sous-méthodes. L'une chargée de l'addition et soustraction et l'autre de la multiplication et division. La méthode calcul doit appeler l'une ou l'autre des sous-méthodes. Corriger la gestion des exceptions.

3. Modifier CalculException pour contenir l'opérateur et les valeurs d'opérande. Surcharger également (ou réécrire) la méthode public String getMessage en retournant un message formaté avec Message d'erreur et opération effectuée.

Image non disponible

2.2. Indices pour l'énoncé

1. Cette exception doit être obligatoirement prise en compte lors de la compilation, donc construite à partir de la classe java.lang.Exception. Pour le traitement des exceptions de vos tests, faire un simple appel à la méthode printStackTrace de l'exception.

2. Penser à bien reprendre la signature avec l'exception dans les sous méthodes.

3. Il vous faut compléter votre classe CalculException pour qu'elle comprenne les champs operateur et operandes. La mise à jour de ces champs se fera par le constructeur. Pour créer une chaîne formatée, vous pouvez employer l'instruction String.format( "%2.2f+%2.2f", 10, 20 ) qui créera dans cet exemple une chaîne 10.00+20.00.

3. Correction "Contrôle de flux"

1. Nous avons employé une première boucle for pour la valeur du premier opérande i puis à chaque itération nous employons une deuxième boucle de type while pour la valeur du deuxième opérande j et nous affichons le résultat dans la console par l'instruction System.out.println. La deuxième boucle nécessite une gestion de l'indice de boucle par j++(<=>j=j+1).

 
Sélectionnez

public class TestCalcul {
	public static void main( String[] args ) {
		for ( int i = 1; i < 10; i++ ) {
			int j = 1;
			while ( j < 10 ) {
				System.out.println( i + "*" + j + "=" + ( i * j ));
				j++;
			}
		}
	}
}

2. Dans la table de division, il faut faire attention à la division par zéro qui peut déclencher une exception java.lang.ArithmeticException. Il existe plusieurs méthodes pour résoudre ce problème. La première, telle que nous la présentons ci-dessous, emploie le mot-clé continue pour continuer la boucle sans effectuer le traitement qui suit. Comme nous sommes dans une boucle while, il ne faut pas oublier d'augmenter la valeur de l'indice par j++. Une autre solution serait simplement de faire un test sur la valeur de j avant l'instruction d'affichage dans la console, ou bien encore de faire un saut de valeur lors de l'incrémentation pour que j passe de 0 à 1 (évitant une itération en trop). Enfin, il est également possible de prendre en compte l'exception par un try catch ce qui évite une interruption de l'exécution.

 
Sélectionnez
		
public class TestCalcul {
	public static void main( String[] args ) {
		for ( int i = -9; i < 10; i++ ) {
			int j = -9;
			while ( j < 10 ) {
				if  (j == 0 ) {
					j++;
					continue;
				}
				System.out.println( i + "/" + j + "=" + ( i / j ));
				j++;					
			}
		}
	}
}

3. Nous employons l'instruction switch/case/default pour afficher dans la console chaque calcul. Il ne faut pas oublier le break dans les blocs case et default servant à interrompre l'exécution du switch, sinon le prochain bloc case serait exécuté. Dans la méthode principale de notre classe, nous sommes tenus de créer un objet de type Calculatrice pour invoquer la méthode calcul. Il aurait été aussi possible de rendre la méthode calcul statique évitant ainsi l'allocation d'un objet pour appeler la méthode. Nous employons l'instruction System.out.printf pour afficher l'opération, il est également possible bien que moins pratique d'employer System.out.println( operande1 + "+" + ope-rande2 + "=" + ( operande1 + operande2 ) ) par exemple.

 
Sélectionnez

public class Calculatrice {
	void calcul( char operateur,double operande1, double operande2) {
		switch( operateur ) {
		case '+' : 
			System.out.printf( "%2.2f+%2.2f=%2.2f\n", operande1, operande2, operande1 + operande2 );
			break;
		case '-' :
			System.out.printf( "%2.2f-%2.2f=%2.2f\n" , operande1, operande2, operande1 - operande2 );
			break;
		case '*' :
			System.out.printf( "%2.2f*%2.2f=%2.2f\n", operande1, operande2, operande1 * operande2 );
			break;
		case '/' :
			if ( operande2 == 0 ) {
				System.out.printf( "%2.2f/0 = Operation impossible !\n", operande1 );
			} else
				System.out.printf( "%2.2f/%2.2f=%2.2f\n", operande1, operande2, operande1 / operande2 );
			break;
		default :
			System.out.println( "Operateur " + operateur + " inconnu" );
		}
	}
	public static void main(String[] args) {
		Calculatrice c = new Calculatrice();
		c.calcul( '+', 1.5, 2.5 );
		c.calcul( '-', 1, 2 );
		c.calcul( '/', 1, 0 );
		c.calcul( '/', 1, 2 );
		c.calcul( '*', 1, 2 );
		c.calcul( '!', 1, 2 );
	}
}

4. Correction "Exceptions"

1. Commençons par écrire l'exception CalculException. A cette étape, nous n'allons rien faire d'autre que d'afficher un message avec l'erreur de calcul. Il est inutile de créer un champ à cet effet dans cette exception puisque c'est déjà pris en compte par la classe parente Exception (et indirectement par Throwable).

 
Sélectionnez

public class CalculException extends Exception {
	public CalculException( String message ) {
		super( message );
	}
}

Maintenant, modifions la classe Calculatrice en ajoutant dans la signature de la méthode calcul l'obligation pour le code appelant de traiter l'exception CalculException.

 
Sélectionnez

public class Calculatrice {

	double calcul( char operateur,double operande1, double operande2)
		throws CalculException {
		switch( operateur ) {
		case '+' : 
			return ( operande1 + operande2 );
		case '-' :
			return operande1 - operande2;
		case '*' :
			return operande1 * operande2;
		case '/' :
			if ( operande2 == 0 )
				throw new CalculException( "Division par zero" );
			return operande2 / operande2;
		default :
			throw new CalculException( 
					"Operateur " + operateur + " inconnu" );
		}
	}

	public static void main(String[] args) {
		Calculatrice c = new Calculatrice();
		try { 
			System.out.println( c.calcul( '+', 1, 2 ) ); 
		} 
		catch( CalculException e ) {
			e.printStackTrace();
		}
		try { 
			System.out.println( c.calcul( '-', 1, 2 ) ); } 
		catch( CalculException e ) {
			e.printStackTrace();
		}
		try { 
			System.out.println( c.calcul( '/', 1, 0 ) ); } 
		catch( CalculException e ) {
			e.printStackTrace();
		}
		try { 
			System.out.println( c.calcul( '*', 1, 2 ) ); } 
		catch( CalculException e ) {
			e.printStackTrace();
		}
		try { 
			System.out.println( c.calcul( '!', 1, 2 ) ); } 
		catch( CalculException e ) {
			e.printStackTrace();
		}
	}
}

A noter que nous devons maintenant pour chaque appel de la méthode calcul prendre en compte les erreurs de calcul grâce aux instructions try/catch. Cet ensemble d'instructions délimite le code à "risque" et le code palliatif. Le code à "risque" est ici l'appel à la méthode calcul qui peut soulever un problème, et le code palliatif est simplement un affichage dans la console de l'origine du problème par l'instruction e.printStackTrace. A noter que le choix ici de rendre le traitement de l'exception CalculException obligatoire est excessif mais souligne avant tout l'intérêt des exceptions, il aurait été sans doute plus pratique de considérer l'exception CalculException comme étant une RuntimeException, cas évitant l'obligation de traitement et affichant dans la console la pile d'exécution. On considère cette dernière possibilité comme étant plus souhaitable pour les erreurs de manipulation d'une méthode (mauvais arguments en appel).

2. Il nous faut créer deux nouvelles méthodes. L'une chargée des additions et soustractions (calculAddSous) et l'autre de la multiplication et division (calculMulDiv). A noter que seule la méthode calculMulDiv va soulever une erreur puisqu'elle gère la division par zéro, elle doit donc aussi contenir dans sa signature l'exception CalculException. Le code des méthodes calculAddSous et calculMulDiv, n'effectue qu'un test d'opérateur en considérant qu'il n'y a pas d'alternative, une instruction else aurait amélioré la lisibilité du code mais n'apporte aucune plus value réelle puisque l'instruction return du premier test d'opérande interrompe l'exécution du bloc. De plus on peut considérer que les méthodes calculAddSous et calculMulDiv ne seront faîtes que pour un usage interne donc pas d'appel en dehors de la méthode calcul et pas de besoin de vérifier la cohérence de l'opérande.

 
Sélectionnez

double calcul( char operateur,double operande1, double operande2)
		throws CalculException {
		switch( operateur ) {
		case '+' : 
		case '-' :
			return calculAddSous( operateur, operande1, operande2 );
		case '*' :
		case '/' :
			return calculMulDiv( operateur, operande1, operande2 );
		default :
			throw new CalculException( 
					"Operateur " + operateur + " inconnu" );
		}
	}

	double calculAddSous( char operateur, double operande1, double operande2 ) {
		if ( operateur == '+' )
			return operande1 + operande2;
		return operande1 - operande2;
	}
	
	double calculMulDiv( char operateur, double operande1, double operande2 ) throws CalculException {
		if ( operateur == '/' ) {
			if ( operande2 == 0 )
				throw new CalculException( "Division par zero" );			
			return operande1 / operande2;
		}
		return operande1 * operande2;
	}

3. Il suffit de compléter l'exception pour contenir l'opérateur et les deux opérandes. On complète le constructeur pour stocker ces valeurs. La méthode getMessage est réécrite pour adopter un nouveau comportement (mécanisme de surcharge de méthode), ce comportement consiste à créer une nouvelle chaîne de caractères avec l'instruction String.format qui reprend le même principe que l'instruction System.out.printf mais retournant par contre la chaîne formatée sans l'ajouter dans la console. Il serait également possible d'employer la classe utilitaire java.util.Formatter ou bien de faire le formatage grâce à l'opérateur + qui supporte les chaînes ( message + " " + operande1 + operateur + operande2 ).

 
Sélectionnez

public class CalculException extends Exception {
	private char operateur;
	private double operande1, operande2;

	public CalculException( 
			char operateur, 
			double operande1, 
			double operande2, 
			String message ) {
		super( message );
		this.operateur = operateur;
		this.operande1 = operande1;
		this.operande2 = operande2;
	}

	public String getMessage() {
		return String.format( "Erreur %s pour operation %2.2f%c%2.2f", 
				super.getMessage(), operande1, operateur, operande2 );
	}	
}

Il reste maintenant à modifier tous les codes de la classe Calculatrice levant l'exception CalculException pour prendre en compte le nouveau constructeur :

Premier cas :
Sélectionnez

throw new CalculException( 
					operateur,
					operande1,
					operande2,
					"Operateur inconnu" );
Deuxième cas :
Sélectionnez

throw new CalculException(operateur, operande1, operande2, "Division par zero");

5. Ouvrage

Cette série de TPs est issue du livre Java 6 (297 pages aux éditions ENI)
http://www.abrillant.com/ouvrage.html

6. L'auteur

Pour me présenter rapidement, je suis formateur Java & XML. Je travaille en région parisienne mais je peux me déplaçer dans toute la france si l'hôtel et le déplacement sont pris en compte dans la prestation. Mon CV est disponible ici : http://www.abrillant.com/cv.html.

J'ai à mon actif quelques réalisations :

Vous trouverez davantage d'informations (tarifs, types de cours...) sur mon site personnel : http://www.abrillant.com

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2008 Alexandre Brillant. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.