Introduction
Introduction
Logiciels
- Gradle (obligatoire)
- Un éditeur de code (au choix), par exemple Eclipse, IntelliJ ou VS Code
- Java JDK 17
Contenu du cours
- Exceptions
- Tests
- Nouveautés Java
- Évènements
- Types génériques
- Réflexion?
Exceptions
On va surtout utiliser Exception et Runtime Exception, mais pas directement (on va plus tot utiliser des exceptions dérivées de ceux-là, tel que NullPointerException ou IllegalArgumentException).
Par défault, le comportement d’une exception est de print l’erreur dans la console, cependant on ne va pas tellement l’utiliser en cours car on va utiliser un système de logging plus élaboré.
Try - catch
try {
// On essaye d'exécuter un certain code ici...
} catch (NullPointerException e) {
// Le code ici s'exécutera si il y a une NullPointerException et l'erreur sera mise dans la variable e.
} catch (NullPointerException | IndexOutOfBoundException e) {
// Le code ici s'exécutera dans le cas d'une NullPointerException ou d'une IndexOutOfBoundException et sera mise dans la variable e.
}
// Si aucun problème n'est arrivé ou qu'elle a été bien catchée, le code ici s'exécutera...
Les try-catch permettent d’exécuer son propre code dans le cas d’une erreur.
Réexécution de fonction
Si on veut réexécuter une fonction il vaut mieux éviter de rappeller simplement la fonction récursivement dans le catch car si une erreur persiste, cela augmente grandement le stack des fonctions appellée ce qui peut mener à faire crash le programme.
Il vaut mieux utiliser un do-while
// On initialise les variables en dehors de la boucle
boolean locked = false;
int entier = 0;
do {
System.out.print("Entrer un entier : ");
try {
entier = lireEntier();
// Si le code a fonctionné, on remet le locked à false pour sortir de la boucle
// On doit le remettre à false car si elle a raté la première fois, le locked aura été mis à true par le catch
locked = false;
} catch {
// Si un soucis survient, on met la variable locked à true, pour que la boucle réexécute le code
// Il n'y a ainsi aucune récursion, donc pas de risque de stackoverflow
locked = true;
}
} while (locked);
Throw - throws
public class PersonalException extends Exception {
// Ici on met le code de l'exception, par exemple on peut y mettre des messages d'erreurs, des fonctions spéciales, etc.
}
// La méthode suivante retourne une exception
public static void method() {
// Si quelque chose ne fonctionne pas on peut retourner notre exception custom
throw new PersonalException();
}
On peut créer nos propre exceptions pour des cas particulier de nos programmes en étendant la classe Exception puis en utilisant throw new pour l’appeller.
Finally
try {
// On essaye d'exécuter un certain code
} catch (NullPointerException e) {
// On exécute le code ici si le code dans le try ne fonctionne pas
} finally {
// Quoi qu'il arrive, le code ici sera exécuté, même si le catch retourne une exception.
}
// Si une erreur arrive dans catch ou finally, le code ici ne sera pas exécuté
Lorsque l’on veut qu’un code s’exécute quoi qu’il arrive, on peut utiliser le bloc finally, ainsi même si l’un des catch retourne une exception, on exécutera quand même le bloc finally.
Tester les exceptions
On peut également tester des exceptions avec assertThrows
assertThrows(RunTimeException.class, ()=>maMethode());
On passe directement la méthode à assertThrows. La syntaxe étrange s’appelle une lambda, c’est une fonction anonyme temporaire qui exécute la méthode à tester.
Cette lambda est nécessaire, sinon on passe le résultat de maMethode à la place de passer la méthode elle même.
La fonction assertThrows va ensuite tester pour voir si une exeception est émise par la méthode, et si oui, elle va tester que l’exception est bien de la classe RunTimeException.
Moteur de production (gradle)
L’objectif est d’automatiser les actions pour produire un logiciel, gérer les dépendances, les détecter et adapter la production du logiciel à la platforme. Gradle est un système qui permet d’automatiser tout ça.
Cela permet donc de rendre un projet indépendant de l’environement de développement de la personne qui écrit le code, car Gradle va automatiquement gérer toutes les dépendences nécessaires.
Historique des moteurs de production
Que font Gradle et Maven
La compilationLe packaging (jar, war, etc)Gestion des dépendencesGénération de la documentationGestionnaire de sourcesAccès au depot des gestinnaires des dépendencesLe déploiement en différents environements (test, développement, production, etc)
Avantage de Gradle
Plus rapidePlus flexible (pas limité à Java, contrairement à Maven)Fichier de config et plus simpleGestion des dépendances plus complèteIndépendantMultilangage
Configuration de Gradle
settings.gradlequi est à la racine du projet et contient le nom du projet ainsi que l’ensemble des sous-projetsbuild.gradleest dans chaque (sous-)projet et contient l’ensemble des éléments utile pour compiler le projet (version de Java, dépendance, , tests, PMD, etc)
Liste des librairies
On peut rechercher les libraries sur le site MVN Repository.
Définition librarie
On ne s’amuse pas à réinventer la roue dès que l’on veut faire un programme. Du coup on va réutiliser des composants qui ont déjà été fait par d’autres personnes. Une librarie c’est exactement ça, c’est une collection d’outils qui permettent de programmer plus facilement et plus rapidement sans devoir réinveter les même choses en boucle.
Identification d’une dépendence/librarie
Il y a 3 éléments qui identifie une dépendence :
Legroup idqui défini le groupe des librairiesLeartifact idqui défini la dépendence dans le groupeLaversionde la dépendence
Il est important de vérifier la version des dépendences qui ne sont pas toujours compatibles entre elles et il faut éviter de prendre des versions trop vieilles.
Dernière fonctionalités utiles du JDK 17
Depuis JDK 8
Les lambdas qui sont des fonctions anonymes dans des variablesLes interfaces fonctionnelles, c’est comme une interface mais pour une seule méthode pour les lambdasDefault methods in interfaces, qui permettent de mettre du code par défault dans des interfacesStream API, permet de mettre une liste et de la traiter de manière fonctionnelle. Par exemple à la place d’utiliser des boucles on peut simplement faire un.filter(n -> n % 2 == 0)sur un streamDate and time API qui permet de simplifier l’accès au date et au temps
Stream API
Pour expliquer plus en détails les avantages de la stream API, voici quelques exemples de code avec et sans stream.
Les streams API sont assez important et sont attendu à l’AI.
Exemple 1Sans stream api :List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); for (int number: numbers) { if (number % 2 == 0) { System.out.println(number); } }Avec stream api :List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.stream().filter(n -> n % 2 == 0).forEach(System.out::println);Exemple 2Sans stream api :List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); for (String name: names) { System.out.println(name.toUpperCase()); }Avec stream api :List<String> names = Arrays.asList("Alice", "Bob", "Charlie"); names.stream().map(String::toUpperCase).forEach(System.out::println);