Formation Java / Spring Boot pour développeurs COBOL
À l’issue de cette troisième journée (qui débordera sur le Jour 4), vous serez être capable de :
primitifs
objets
notion de valeur et référence
String
double
BigDecimal
Cette journée conditionne la compréhension de tout ce qui suivra (POO, collections, JPA) de la semaine suivante.
En COBOL, vous avez une vision très claire des données :
DATA DIVISION
En Java :
Cette différence est l’une des sources majeures de bugs pour les débutants Java. Nous allons donc l’expliquer lentement, avec des analogies COBOL puis nous pourrons pas la suite ne présenter que du code Java.
J’ai conçu le cours de la manière suivante :
full Java
Dans ce cours, nous allons voir les bases de la syntaxe en Java
Bref aperçu de la notion Objet…
Lien vers les notions de base en Java
Vous le savez, une variable Java se caractérise par :
nom
type
stocker une donnée temporairement en mémoire
Syntaxe générale : type nomDeVariable;
type nomDeVariable;
int nombreDeJourFormation;
ou directement avec une valeur : type nomDeVariable = valeur;
type nomDeVariable = valeur;
int nombreDeJourFormation = 30;
En Cobol, on a des niveaux de données “ordonnées” de manière séquentielle, des groupes de données, des variables indépendantes et l’utilisation de l’indentation. Cela dans le but de représenter des structures de données complexes. En Java, nous sommes dans un univers objet avec des variables (attributs) et des objets issus de classes. On utilise aussi l’indentation pour une meilleure lisibilité du code, mais pas de notion de niveaux, .
En Cobol :
01 SOLDE. 05 SOLDE-COMPTE PIC 9(7)V99. 05 DATE-MAJ. 10 ANNE-MAJ PIC 9(4). 10 MOIS-MAJ PIC 9(2). 10 JOUR-MAJ PIC 9(2).
Soit :
En Java (première approche) en reprenant le code en Cobol comme exemple.
Ne tenez pas compte du mot-clé private pour le moment !
private
public class Client { private String idClient; // PIC X(10) private String nom; // PIC X(50) private double soldeCompte; // 05 SOLDE-COMPTE PIC 9(7)V99 (équivalent à un double) private DateMaj dateMaj; // 05 DATE-MAJ. ... } // autre classe dans un autre fichier Java pour la date de mise à jour (il exsite des classes spécifiques) public class DateMaj { private int annee; // PIC 9(4) private int mois; // PIC 9(2) private int jour; // PIC 9(2) } ...
Attention : Le type double ne garantit pas la précision décimale.
Les types primitifs représentent des valeurs simples, stockées directement en mémoire (Stack ou pile).
Principaux types :
Exemple :
int nombreOperations = 5; boolean compteActif = true;
En COBOL :
05 NOM-CLIENT PIC X(30).
String nomClient; //ou avec constructeur String nomClient = new String();
String n’est pas un type primitif, c’est un objet manipulé par référence, mais Java masque cette complexité pour en simplifier l’usage. C’est pour cette raison que l’on peut lui affecter une valeur de 2 manières différentes.
String nomClient == "Dubosc"; //ou avec constructeur String nomClient = new String("Dubosc");
int a = 10; int b = a; // Copie de la valeur de a dans b b = 20; // Modifie seulement b
Résultat :
Explication :
Pour bien illustrer que Java passe les références par valeur, utilisons un objet mutable (comme un tableau ou une classe personnalisée que nous verrons ultérieurement) :
int[] tableau1 = {1, 2, 3}; int[] tableau2 = tableau1; // Copie de la référence tableau2[0] = 99; // Modifie le CONTENU de l'objet pointé System.out.println(tableau1[0]); // Affiche 99 System.out.println(tableau2[0]); // Affiche 99
Mais attention : Si on fait tableau2 = new int[]{4, 5, 6};, tableau1 reste inchangé (car on change la référence de tableau2, pas le contenu de l’objet original).
Schéma mémoire :
tableau1 ----> [99, 2, 3] (adresse 0x300) tableau2 ----> [99, 2, 3] (même adresse 0x300)
class Personne { String nom; Personne(String nom) { this.nom = nom; } } public class Main { public static void main(String[] args) { Personne p1 = new Personne("Alicia"); Personne p2 = p1; // Copie de la référence p2.nom = "Joachim"; // Modifie l'objet pointé par p1 et p2 System.out.println(p1.nom); // affiche "Joachim" System.out.println(p2.nom); // affiche "Joachim" } }
Mais si on fait p2 = new Personne("Agnès");, p1 reste inchangé (car on change la référence de p2).
p2 = new Personne("Agnès");
Avant p2.nom = "Joachim": p1 ----> Personne("Alicia") (adresse 0x400) p2 ----> Personne("Alicia") (même adresse 0x400) Après p2.nom = "Joachim": p1 ----> Personne("Joachim") (0x400) p2 ----> Personne("Joachim") (0x400)
Nous pourrions aussi écrire un exemple avec des objets String mais comme String est IMMUABLE, toute affectation est une création d’un nouvel objet et par conséquent, une référence différente. En Java, une variable objet contient une adresse, pas la donnée elle-même.
Résumé sous forme de code (à tester):
// passage par valeur (primitif) int x = 5; int y = x; // y est une copie de x y = 10; // x reste 5 System.out.println("x = "+x); System.out.println("y = "+y); // passage par valeur (référence à un objet immuable) String a = "Bonjour"; String b = a; // b est une copie de la référence de a System.out.println("b = a donc b = "+b); b = "Au revoir"; // b pointe vers un nouvel objet, a reste "Bonjour" System.out.println("a = "+a); System.out.println("b = Au revoir donc b = "+b); // passage par valeur (référence à un objet mutable) int[] t1 = {1, 2, 3}; int[] t2 = t1; // t2 est une copie de la référence de t1 t2[0] = 99; // Modifie l'objet pointé par t1 et t2 en affectant 99 à la place de 1 // t1 est maintenant {99, 2, 3} System.out.println("t1 = "+t1); // on voit la référence de l'objet (pas le contenu) System.out.println("t2 = "+t2); // on voit que la référence de l'objet est la même (idem)
Quelques explications sur la gestion de la mémoire…
Test simple :
double a = 0.1; double b = 0.2; System.out.println(a + b);
Résultat affiché :
0.30000000000000004
Ce comportement est normal pour l’informatique binaire, mais inacceptable en contexte bancaire !
BigDecimal permet :
import java.math.BigDecimal; BigDecimal a = new BigDecimal("0.1"); BigDecimal b = new BigDecimal("0.2"); BigDecimal resultat = a.add(b);
0.3
Règles d’or BigDecimal
Pour interagir avec l’utilisateur, on utilise la classe Scanner :
Scanner
import java.util.Scanner; Scanner scanner = new Scanner(System.in); System.out.print("Entrez le solde initial : "); String saisie = scanner.nextLine(); // Conversion en BigDecimal BigDecimal solde = new BigDecimal(saisie);
Objectif :
simuler un calcul COBOL en Java
BigDecimal solde = new BigDecimal("1000.00"); BigDecimal debit = new BigDecimal("200.50"); BigDecimal credit = new BigDecimal("150.00"); solde = solde.subtract(debit); solde = solde.add(credit); System.out.println("Solde final : " + solde);
Scanner scanner = new Scanner(System.in); System.out.print("Solde initial : "); BigDecimal solde = new BigDecimal(scanner.nextLine()); System.out.print("Montant débit : "); BigDecimal debit = new BigDecimal(scanner.nextLine()); solde = solde.subtract(debit); System.out.println("Nouveau solde : " + solde);
Objectif : reproduire un traitement COBOL simple en Java
Consignes :
Objectif : Constater concrètement le problème de précision
Comparer les résultats
Objectif : introduire une règle métier simple
Consigne : si le solde final est négatif, afficher : “ATTENTION : COMPTE À DÉCOUVERT”
import java.math.BigDecimal; import java.util.Scanner; public class CalculSolde { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Solde initial : "); BigDecimal solde = new BigDecimal(scanner.nextLine()); System.out.print("Débit : "); BigDecimal debit = new BigDecimal(scanner.nextLine()); System.out.print("Crédit : "); BigDecimal credit = new BigDecimal(scanner.nextLine()); solde = solde.subtract(debit); solde = solde.add(credit); System.out.println("Solde final : " + solde); } }
Points d’attention :
double a = 0.1; double b = 0.2; System.out.println(a + b); BigDecimal x = new BigDecimal("0.1"); BigDecimal y = new BigDecimal("0.2"); System.out.println(x.add(y));
Conclusion :
if (solde.compareTo(BigDecimal.ZERO) < 0) { System.out.println("ATTENTION : COMPTE À DÉCOUVERT"); }
double par réflexe
new BigDecimal(0.1)
import java.math.BigDecimal
Aujourd’hui, vous avez posé les bases métier :
Décision d’architecture progressive :
Vous savez :
On abordera :