Java Avancé Révisions La technologie Java En quelques mots : ● Orienté objet ● Simple, robuste, dynamique et sécurisé ● Indépendant de la plateforme (VM) ● Semi-compilé/semi-interprété ● Bibliothèque standard importante (JDK API) Architecture en C Code en Ascii 010 Compilateur ● ● Le code est compilé sous forme objet relogeable L'éditeur de liens lie les différents fichiers objets entre eux pour créer l'exécutable 010 010 010 Éditeur de lien 01 0 Plateforme + OS Architecture en Java Code en Unicode Compilateur ● ● 0xCaf 0xCaf 0xCaf 0xCaf API Le code est compilé dans un code intermédiaire (bytecode) La Machine Virtuelle interprète le code 0xCaf 0xCaf ClassLoader VM Plateforme + OS Architecture en Java ● Un JIT (Just In Time Compiler) est un générateur de code assembleur à partir du bytecode appelé à la volée par la VM 010 ● Le ramasse-miette (garbage collector) récupère les objets non utilisés 0xCaf 0xCaf 0xCaf 0xCaf 0xCaf 0xCaf JRE ClassLoader JIT VM Plateforme + OS GC Organisation des sources ● ● ● ● Les classes appartiennent à un paquetage (directive package) Le paquetage par défaut (directive package absente) ne doit pas être utilisé sauf pour des tests Les sources du paquetage a.b.c doivent être placées dans le répertoire a/b/c En règle générale, on place les sources dans src et les fichiers de bytecode dans classes La directive import ● La directive import permet d'éviter de nommer une classe avec son paquetage public class MyButcher { public static void main(String[] args) { fr.umlv.jbutcher.Rule rule= new fr.umlv.jbutcher.Rule(); } } import fr.umlv.jbutcher.Rule; public class MyButcher { public static void main(String[] args) { Rule rule=new Rule(); } } ● ● Le compilateur comprend que Rule a pour vrai nom fr.umlv.jbutcher.Rule Le code généré est donc identique Import * ● Indique au compilateur que s'il ne trouve pas une classe, il peut regarder dans les paquetages désignés import java.util.*; import fr.umlv.jbutcher.*; public class MyButcher { public static void main(String[] args) { ArrayList list=new ArrayList(); Rule rule=new Rule(); } } ● Ici, ArrayList est associé à java.util.ArrayList et Rule à fr.umlv.jbutcher.Rule Import * et ambiguïté ● ● Si deux paquetages possèdent une classe de même nom et que les deux sont importés en utilisant *, il y a ambiguïté On peut lever l'ambiguïté en important explicitement une des deux classes import java.util.*; import java.awt.*; public class ImportClash { public void f() { List list=... // oups } } import java.util.*; import java.awt.*; import java.util.List; public class ImportClash { public static void f() { List list=... // ok } } Import * et maintenance ● import * peut poser un problème de maintenance si des classes peuvent être ajoutées dans les paquetages utilisés import a.*; import b.*; public class ImportClash { public static void f() { A a=new A(); B b=new B(); } } package a Class A package b Class B Class B Import statique ● Permet d'accéder aux membres statiques d'une classe dans une autre sans utiliser la notation '.' import java.util.Scanner; import static java.lang.Math.*; public class StaticImport { public static void main(String[] args) { Scanner in=new Scanner(System.in); System.out.println("donner un nombre :"); double value=sin(in.nextDouble()); System.out.printf("son sinus est %f\n",value); } } ● Notation : import static chemin.classe.*; Import statique et scope ● Lors de la résolution des membres, les membres (même hérités) sont prioritaires sur le scope import static java.util.Arrays.*; public class WeirdStaticImport { public static void main(String[] args) { java.util.Arrays.toString(args); // ok toString(args); // toString() in java.lang.Object // cannot be applied to (java.lang.String[]) } } ● Règle de programmation : ne pas utiliser l'import statique Paquetages ● ● La hiérarchie des fichiers source et de bytecode au sein du système de fichiers reflète la hiérarchie des paquetages URL (dont on possède le domaine) à l'envers fr fr.umlv fr.umlv.licence fr.umlv.master fr.umlv.ir fr.umlv.ir.ir1 fr.umlv.ir.ir2 fr.umlv.ir.ir3 fr umlv licence master ir ir1 ir2 ir3 Organisation d'un projet ● ● ● ● ● Les sources sont dans le répertoire src Les fichiers de bytecode sont dans le répertoire classes Les bibliothèques nécessaires (jar et so/dll nécessaires aux jni) sont dans le répertoire lib Le documentation (dont la javadoc) dans le répertoire doc README et build.xml à la racine Compilation des sources ● Les sources sont compilées avec javac – -d destination (par défaut, le fichier de bytecode est dans le même répertoire que le fichier source) ● ● le compilateur crée les sous répertoires – -classpath/-cp localisation des fichiers de bytecode et des archives jar – -sourcepath localisation des fichiers sources (pour les dépendances) – -g:none n'ajoute pas les information de déboggage Avec la hiérarchie précédente javac -d classes -classpath classes:lib/truc.jar -sourcepath src src/fr/umlv/projet/Toto.java En plus ● – -Xlint:deprecation affiche le code déprécié – -Xlint:unchecked affiche le code dont l'exécution contient un cast non vérifié à l'exécution ― à cause des classes génériques (template) ; il y a risque de ClassCastException à un endroit inattendu lors de l'exécution Le compilateur rappelle ces options quand elles pourraient être utiles. Exécuter une classe ● ● On lance la machine virtuelle hotspot avec la commande java – -cp/-classpath location des archives jar et des classes – -ea active les assertions – -Dname=value change ou ajoute une propriété système – -server active certaines optimisations – -jar exécute un jar exécutable (-cp ignoré) Avec la hiérarchie précédente java -cp classes:lib/truc.jar fr.umlv.projet.Toto Variable d'environnement java et certains programmes annexes utilise certaines variables d'environnement : ● ● CLASSPATH qui correspond aux répertoires où chercher les classes – si -cp ou -classpath est présent, java et javac n'en tient pas compte – les chemins sont séparés par : sous UNIX (comme $PATH), et ; sous windows (comme %PATH%) – la valeur par défaut est . (même sous windows) JAVA_HOME qui correspond au répertoire racine du JDK Variables d'environnements Archive java ● ● ● La commande jar permet de créer un archive contenant les fichiers de classes et les ressources Une archive contient des méta-données contenues dans le manifest Pour créer un archive sans manifest cd classes jar cvMf ../archive.jar . ● avec manifest jar cvmf ../manifest ../archive.jar . jar cvf ../archive.jar . ● manifest par défaut Manifest ● Le manifest est un fichier texte contenant une suite de lignes CLEF: VALEUR (l'espace après le : est obligatoire) ● Clef générales : – Manifest-Version – Created-By – Class-Path : URL relatives à l'emplacement du jar vers des bibliothèques externes séparées par des espaces (/ à la fin des répertoires) ● – On ne doit pas recopier tout grosselib.jar dans son jar Main-Class : nom (complet) de la classe à exécuter pour rendre le jar exécutable Désassembleur de bytecode ● javap permet d'afficher les informations contenues dans les fichiers de classes – -classpath localisation des fichiers – -public/-protected/-package/-private visibilité minimum des membres affichés – -c affiche aussi le code et pas seulement les en-têtes – -s affiche le type (format interne de la VM) des membres de la classe – -verbose affiche le nombre de variables locales, la taille de la pile de chaque méthode et le contenu du constant pool Script ant ● ● Les scripts ant sont l'équivalent du makefile pour les projets java C'est un fichier XML appelé build.xml <project name="mon projet" default="compile" basedir="."> <description> Description du projet </description> <!-- déclaration des tâches --> </project> Script ant ● Les tâches ont la forme suivante <target name="run" depends="compile,jar"> <!-- actions à effectuer --> </target> ● Chaque action est une balise XML dont les attributs et les sous-balises sont spécifiques <javac srcdir="src" destdir="classes" debug="true"/> <javac srcdir="src" destdir="classes" debug="true"> <compilerarg value="-Xlint:deprecation"/> <compilerarg value="-Xlint:unchecked"/> </javac> Script ant ● Pour exécuter des classes <java classpath="classes" classname="fr.umlv.projet.Main"/> <java jarfile="projet.jar"/> ● pour détacher le processus d'ant (par exemple pour une interface graphique) <java fork="true" jarfile="projet.jar"/> Paramétrage ● ● On peut déclarer des paramètres que l'on peut utiliser par la suite Cela permet de récupérer facilement un build.xml <property name="src" location="src"/> <property name="build" location="classes"/> <property name="mainclass" value="fr.umlv.projet.Main"/> <target name="compile"> <javac srcdir="${src}" destdir="${build}"/> </target> <target name="run" depends="compile"> <java classpath="${build}" mainclass="${mainclass}"/> </target> Tags javadoc ● La javadoc (entre /** et */) peut contenir différents tags : – @see : lien vers une méthode, classe ou champ ● @see fr.umlv.Classe#methode(String,int,fr.umlv.Classe) – @param x : décrit le paramètre x – @return : décrit ce que renvoie la méthode – @throws E : décrit dans quels cas l'exception E est lancée.