.. title: Java: tribulations d'un développeur C++ .. contents:: Motivation ---------- Bien que développeur C/C++, il m'a fallu apprendre du Java pour terminer une partie de projet non-prévue. Ces notes éparses ne sont pas un vrai tutoriel: elles condensent ce qui a été nécessaire à un développeur déjà expérimenté pour passer à une certaine efficacité dans un langage voisin. Pour (re)débuter sur Java ------------------------- Lancer ou examiner un programme existant ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``java ``: lancer le programme (sans l'extension ``.class``); - ``jar -xf `` : extrait les fichiers ``.class`` composant l'objet; - ``javap ``: désassemble la classe correspondante; Principaux atouts du langage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - La caractéristique la plus connue du langage est la présence d'un «Garbage collector», dont l'implémentation est d'ailleurs facilitée par le fait que tous les objets dérivent d'une unique classe. - Classes ``abstract`` (pas d'implémentation), et ``interface`` (implémentation obligatoire par les successeurs); - Polymorphisme des objets (sans besoin de mot-clef comme en C++); - Vérification de downcast dans le langage; - Gestion (et obligation) des exceptions; - Multithreading (et gestion des ressources par ``synchronized``); - Distribution, et programmation réseau; Vocabulaire ~~~~~~~~~~~ Java brouille (tout comme C++) les frontières entre fonctions et méthodes. En principe: - une fonction: produit un résultat, mais n'a pas d'effet de bord (si elle est «pure»); - une méthode peut changer des choses; Concepts et syntaxe ------------------- Visibilité ~~~~~~~~~~ - ``import ...``; importe un symbole ou un package particulier - ``import static .\*;`` : utilise tous les symboles sans préfixe. Querelles d'héritage ~~~~~~~~~~~~~~~~~~~~ Le mot-clef ``final`` (voir `a plusieurs sens `__): - ``final `` : pas de classe fille; - ``final `` : pas de redéfinition dans les classes filles; - ``final `` : est affectée une seule fois, à la déclaration OU dans le constructeur; cela ne la rend pas forcément constante, car ses méthodes peuvent la modifier; Le mot-clef ``static`` aussi: - pour un membre de classe: sera commun à toutes les instances; - pour un bloc hors-méthode: initialisation exécutée au chargement de classe, et même avant ``main()``; Idem pour `extends `__ Quant à ``this`` et ``super``, ils désignent respectivement la classe courante et la classe mère; Déclarations de fonctions ~~~~~~~~~~~~~~~~~~~~~~~~~ - Une flèche ``->`` définit une fonction anonyme, alias «lambda» : ``(args) -> { expression }``; - Fonctions `variadiques `__: écrire ``f(Object ... ao)`` passe un tableau d’objets ``ao`` à la fonction; Annotations ~~~~~~~~~~~ Ces compléments du langage, d’abord utilisés seulement par Javadoc, on été standardisés par Java5 - Annotation ``@Override``: s'assure que la fonction redéfinit bien un membre de la classe mère: ``@Override public int calcul() { ... }``; - Annotations en général sur le `cours de J-M Doudoux `__ et la `doc Oracle `__; 3 rôles principaux: - fournir des informations au compilateur; - générer du code ou des fichiers de déploiement; - influer (parfois) sur l'exécution; Curiosités et logique ~~~~~~~~~~~~~~~~~~~~~ - ``final`` : une variable locale citée dans un lambda ou une classe anonyme (telle un listener) doit être ``final`` (car on ignore quand les fonctions concernées seront exécutées?), ou «effectively final» en Java 8. Templates ~~~~~~~~~ - Voir `Generic Types `__ : ``class nom { ... }`` - Voir `Generic Methods `__ : `` T1 f(T2,...) {...}`` Les évolutions de Java ---------------------- Les spécifications ~~~~~~~~~~~~~~~~~~ Les spécifications de la `machine virtuelle Java (JVM) `__ montrent bien que, même non-liée au langage Java, elle est pensée pour lui. - Les `specs du langage `__ peuvent éclairer les zones d'ombre. Auteurs: James Gosling, Bill Joy, Guy Steele ... du beau monde! - La JVM ne sachant rien du langage, d'autres, tels Scala, peuvent fort bien tourner dessus. - Par rapport à une spécification hardware normale, la JVM définit: - des ``class`` avec des ``methods`` dont on a les ``reference``; - un ``bytecode``, des instructions pour tableaux avec vérification d'index,... - des exécutions avec ``frame``, synchronisation avec des sections ``monitor``, et instructions JVM pour les ``catch`` Apports de Java 8 ~~~~~~~~~~~~~~~~~ - Changements détaillés dans `What's New in JDK8 `__ - Streams facilitant les conversions. Par exemple de ``Integer[]``\ vers ``int[]``: ``intList.stream().mapToInt(Integer::intValue).toArray();`` - Notion de variable "effectively final", i.e non-modifiée après son initialisation, même sans déclaration ``final``; - Rapprochement avec langage fonctionnel : lambdas; - Annotations de types, et meilleure inférence de type; - Référence de méthode : ``classe::methode``; - Méthodes par défaut dans les interfaces; Cours, Pratiques et Jargon Java ------------------------------- Les cours ~~~~~~~~~ - `les concepts de Java `__; - `les cours Sun/Oracle `__; - Références Oracle: la `référence de l'API `__ ou `toutes les classes `__; - `JMDoudoux.fr `__: copieuse présentation de Java; Présentations rapides par thèmes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - `présentation par notion `__ et `idem chez beginnersbooks.com `__ - `les ressources pour débutant `__ - `un petit cours sur JavaFX `__: remplaçant de Swing qui remplaçait AWT; - `Autre collection de titres `__, dont «Penser en Java v2»; Présentations plus avancées ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Des `Considérations techniques `__ - La `Reflection `__: (capacité du code à s'inspecter et se modifier lui-même). Natif en Python, implémenté via le package ``reflection`` de Java, et utilisé en particulier pour les annotations. - `Les lambdas `__ : voir notamment `Jenkov.com `__ et le `Tutorial Oracle `__; - `Java Technology Network `__: le Technet d'Oracle, apparemment; Bonnes pratiques ~~~~~~~~~~~~~~~~ - `JavaPractices.com `__: déjà ancien, mais dense et concis; - `Writing good Java code `__; - `Docs Oracle `__ ... pas forcément utilisées par Oracle d'ailleurs! Jargon ~~~~~~ - POJO : Plain Old Java Objects (des structures simples, quoi); Pièges du Java -------------- Quelques points qui embêtent notoirement les programmeurs C++. Dans les comparaisons ~~~~~~~~~~~~~~~~~~~~~ Entre objets, l'opérateur ``==`` teste juste l’égalité des références. Ce n'est pas équivalent à l'égalité de contenus (sauf entre singletons). - En fait ``==`` ne vaut qu'entre des objets singletons comme ``enum``, ou entre des non-objets comme ``int``, ``double``, ``boolean``; - L’équivalence entre objets se teste avec ``.equals()``, donc on compare: - deux ``Double`` avec ``.equals()``; - deux ``double`` avec ``==``; Dans les manipulations d'arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tous les arguments sont passés par **copie** d’adresse, donc pour changer un argument: - ne **pas** utiliser ``=``, qui écrasera juste le registre contenant l’adresse de l'argument, non-relu par l'appelant; - modifier les champs via une méthode de l’argument s'il en existe; - sinon créer une classe dont les membres sont les arguments à changer; Dans les manipulations de fichiers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``BufferedWriter`` : perd les octets en attente si détruit avant appel à ``close()``; Erreurs classiques à l'exécution ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``java.lang.UnsatisfiedLinkError: no in java.library.path``: problème dans la recherche d'une bibliothèque native (DLL par ex.); `explication détaillée dans les forums `__ Tâches usuelles --------------- Conversions ~~~~~~~~~~~ - Copier des tableaux : ``clone()`` réalise une copie superficiielle; Lecture/Ecriture ~~~~~~~~~~~~~~~~ *Lecture/Ecriture vers fichiers* - Voir chez Oracle : `Java:Basic IO `__ et `la classe IO `__: classes ``ReadAllBytes``, ``BufferedWriter`` ... - Java 7 a introduit ```java.nio.file.Path`` `__ et de nouvelles façons de faire avec `Files `__; *Analyser des fichiers XML* - Analyser du XML : sur le `Site du Zéro `__, sur `TutorialPoints `__. *Utiliser un logger* - `Tutorial sur Logger `__, et `cet autre tutorial `__ Construction/Analyse de chaînes de caractères ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Lire et découper des chaînes de caractères* Principales méthodes pour obtenir ou découper des chaînes: - ``.readLine()``: null, ou chaîne sans saut ou fin de ligne. - ``.split(,)``: découpe selon ````, en au plus ```` morceaux dont le dernier contient toute la fin de chaîne; - ``StringTokenizer`` : obsolète, un peu plus rapide que ``split()``, car sans regexp; La classe ``Scanner`` est plus souple, quoique beaucoup plus lente: - voir `un article en français `__ - attention, les tokens sont séparés AVANT détection de patterns par ``next()``, prendre autre chose pour isoler des tokens avec espaces (cf classe ``matcher``) *Extraire des nombres* Une méthode simple et un peu paresseuse est la classe `Scanner `__: - voir `un article en français `__; - séparateurs décimaux changeables par la méthode ``.useLocale()``; Choix des séparateurs décimaux en général: - ``Locale.ROOT`` (indépendant de la langue, mais proche anglo-saxon); - ``Locale.UK`` (moins neutre, mais équivaut en principe au précédent); S'il faut reconnaître des nombre sans se préoccuper de la langue: - présentation dans `le tutoriel Oracle `__; - les classes dérivées de ``Number`` (comme ``Double``,\ ``Integer``, ...) ignorent les locales dans leurs méthodes ``.parseXXX()`` ou ``toString()``: cf doc de leur membre ``valueOf()``. *Construire de longues chaînes* Un objet ``String`` étant *unmutable*, en construire un par étapes demande un intermédiaire dynamique comme ``StringBuilder``: - un objet ``StringBuilder`` est réutilisable sans réservation avec la méthode ``.setLength(0)`` (cf `débat sur performances `__); - Attention aux conversions d'accents : `cf codage des String `__ : pour contrôler l'encodage, passer `par OutputStreamWriter `__; Java pour programmeur C++ ------------------------- Tutorial ~~~~~~~~ - `tutorial C++ vers Java `__: Démarrage et arguments du programme ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Dans ``main(String[] args])``, ``args[0]`` est le premier argument, pas le nom du programme; Il est facile de `se tromper dans la classe à lancer `__. Elle doit: - avoir une méthode ``public static void main(String [])``; - être donnée avec son nom de package complet; Conventions du langage ~~~~~~~~~~~~~~~~~~~~~~ - Types élémentaires en minuscules (``int``, ``double``), comparables par ``==``; - Types classe en majuscule, à comparer par ``.equals()``; - Les types élémentaires ont des jumeaux objets (tels ``Integer`` ou ``Double``) en majuscules; - Ces jumeaux servent aux lectures: ``int Integer.parseInt(chaine)``, ``double Double.parseDouble(chaine)`` ... - et aux conversions en chaîne: ``I.toString(..)`` si ``I`` est ``Integer`` (`plus sur les conversions `__); - Exceptions possibles: ``NumberFormatException``, ``NullPointerException``; Changements d'habitudes ~~~~~~~~~~~~~~~~~~~~~~~ Contrairement au C++, Java ne permet pas de redéfinir les opérateurs; En particulier, ``==`` ne teste que l'égalité des références de deux objets. En général, une méthode ``.equals()`` teste l'égalité des contenus. Par ailleurs, les arguments sont passés par copie de référence: - Pour des objets dont on peut modifier le contenu, c'est presque équivalent au passage par référence du C++; - Mais pour des objets «unmutable» comme «String», il est impossible de modifier l'objet d'une référence Opérations mathématiques classiques ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``import java.lang.Math``; Structures de contrôle ---------------------- Les exceptions ~~~~~~~~~~~~~~ Les exceptions dérivent de ``Exception`` voir `explication détaillée `__: - ``catch(Exception e)`` correspond au ``catch(...)`` du C++, avec particularités: - ``catch(ExA|ExB|ExC e)``: catch multiple (Java >7) - ``f(...) throws e1, ..., eN { ... }``: une fonction doit lister les ``checked exceptions`` qu'elle peut produire; - ``checked exception``: celles que l’on peut attraper par ``catch``; - ``unchecked exception``: celles qui terminent le programme de toute manière (ex: ``NullPointerException``); - Syntaxe ``try ... finally ...`` : pour fermer les objets importants en dépit des exceptions. - Syntaxe `try-with-resource `__ : n'oublie pas de fermer un objet. :: try (FileWriter fw=...) { ... } catch (IOException e) { ... } Boucles et itérations ~~~~~~~~~~~~~~~~~~~~~ - ``for(Objet x : Tableau) { ... }`` Structures de données --------------------- Types de base ~~~~~~~~~~~~~ - ``Arrays`` : à la base, tous les éléments d’un Array sont de même type; - ``int``, ``double``, ``boolean``: ne sont pas des objets (contrairement à leurs acolytes en majuscules), et peuvent donc être comparés par ``==``; Enumérations ~~~~~~~~~~~~ - Les `énumérations `__: forcent à utiliser des noms plutôt que des valeurs en dur; Ce sont aussi des singletons, comparables pour une fois avec ``==``; - ``Set`` et ``EnumSet``: utilisation pour `sous-ensemble de type énuméré `__ Collections ~~~~~~~~~~~ - `Java Collections `__, et en particulier `ce résumé `__; cf aussi `un aide-mémoire assez complet `__; - Contrairement aux tableaux de base ``[]``, les collections ne peuvent contenir que des objets, pas des types élémentaires comme ``int``, ``boolean``, .... ; - Interfaces les plus courantes pour les Collections : - ``Set``, ``List``, ``Queue``, ``Deque`` (double-ended queue), ``List``, ``Map``; - ``SortedSet`` et ``SortedMap`` - Implémentations les plus courantes pour les Collections : - ``ArrayList``, ``ArrayDeque`` : interfaces reposant sur tableau dynamique; - Vector\` : comme ArrayList, mais synchronisé entre threads; - ``HashMap``, ``LinkedHashMap``, avec `plusieurs façons d’itérer dessus `__, et des méthodes ``containsKey()``, ``put()``, ``putIfAbsent()``, ``get()``, ``getOrDefault()``; - Convertisseurs: souvent ``toArray()`` ou ``subList()``; - Astuces et conversions entre collections et tableaux: - ``ArrayList AL`` vers ``[] A``: :: T [] A = new T[AL.size()] A = AL.toArray(A) # Verbeux, hein ? A = AL.toArray(new T[0]) # Plus court - Ensemble à partir d'un tableau: :: Set e = new HashSet<>(Arrays.asList(A)) - Initialisations et tris rapides sur ``ArrayList``: :: al = new ArrayList(Arrays.asList(1,2,3,)); al.subList(k,al.size()).clear() : Efface de k à la fin Collections.sort(al); Quelques bibliothèques ---------------------- JavaFX ~~~~~~ Les bases ^^^^^^^^^ - Présentation de référence `chez Oracle `__; - `JavaFX by Example `__: une petite application d'exemple; - `JavaFXTutorials `__; - `Refcard JavaFX sur DZonec.com `__: résumé des notions importantes; - Sur Fedora 25, il faut compiler; Voir `le site OpenJFX `__: quelques différences avec Oracle, expliquées par 'JewelSea' - `Projet 7GUIs `__ : objectif comparer les langages pour des IHM de plus en plus complexes. Quelques classes de base ^^^^^^^^^^^^^^^^^^^^^^^^ - ``GridPane``: éléments à mettre, avec éventuellement un index de ligne/colonne; - ``ComboBox``: ``.getValue()`` renvoie le texte sélectionné, mais pour l'index il faut tester ``.getSelectionModel().isSelected(j)`` sur chacun des ``combo.getItems()``; Bibliothèque JFreeChart ~~~~~~~~~~~~~~~~~~~~~~~ Pour la plupart des graphiques en Java. - Pour commencer: - Site officiel: `jfree.org `__, et `sources sur github `__ - Tutoriels : `une liste `__, `une intro détaillée `__; - Exemples avancés: - avec des seuils: `mettre des seuils sur une ligne `__ - avec des lignes différentes : `choisir le style de ligne `__ - bricolage sur les «renderers» pour `heatmaps avex xyblockrenderer `__ - Intégration / comparaison avec JavaFX - graphiques `en tâche de fond `__ - `ChartCanvas `__ : pour afficher dans JavaFX