Un package permet de regrouper des classes dans un même espace de nom.
Ceci permet d'éviter des conflits de nom entre autre.
Un package est organisé en arborescence et les fichiers .class sont stockés dans une arborescence équivalente au découpage du package.
Les noms de package doivent être en minuscule. Les caractères autorisés sont les lettres, le "_" et le "$".
Exemple :
Package com.company.myapp : /com /company /myapp MyClassOne.class MyClassTwo.class MyClassThree.class
Pour utiliser un package, il faut que le fichier .jar soit dans le CLASSPATH et utiliser la clause import afin de le pas devoir utiliser le fully qualified name.
Pour positionner une classe dans un package, il faut utiliser la clause package en toute premiere ligne.
Exemple :
package com.company.myapp; import java.util.Arrays; import java.awt.*; import java.awt.events.*; import static java.lang.Math.PI; // import des constantes statiques public class MyClassOne { // instructions }
Un package contient :
Le nom de la classe, de l'interface, de l'enumeration doit etre le même que nom du fichier .java.
Le package java.lang est toujours importé par défaut.
Java core divisé en packages suivants qui sont présents dans le fichier rt.jar :
Java possède également des extensions, ce sont les packages commencant par javax :
Une classe est constituée de champs et de méthodes. Son nom commence par une majuscule par convention.
Syntaxe :
[public] class MyClass [ extends ParentClass ] [ implements Interface_1, ..., Interface_n ] { // fields declaration // methods declaration }
Syntaxe de la déclaration des champs :
[access modifiers] ; // Exemple public int age;
Par convention, le nom d'une méthode doit commencer par un verbe.
Syntaxe de la déclaration des methodes :
[access modifiers] ( [ ] ) [throws exception] { // body }; // Exemple public int getAge() { return this.age; }
Le constructeur d'une classe est une méthode particulière.
Nom arbitraire d'arguments dans une méthode : il existe une syntaxe spéciale pour celà :
// Declaration public int myFunction(int... myParam) { int argCount; argCount = myParam.length; } // Exemple d'appel : soit avec un nombre variable d'arguments, soit avec un tableau myFunction(0,1,2); int[] myArray = { 0, 1, 2 }; myFunction (myArray);
Le nom d'un parametre peut parfois être le meme que celui d'un champs de la classe (on parle de shadow field). Dans ce cas, le nom au sein de la méthode se réfère au paramètre, tandis que "this. Le passage des arguments de type primitif se fait par valeur !
Le passage des arguments de type Objet se fait aussi par valeur (la référence de l'objet) !
Exemples :
Un membre peut avoir les modifieurs d'accès suivants : public, protected, private et aucun.
On remarque que par défaut, si aucun modifier n'est précisé, l'accès est "package-private" c'est-à-dire juste un peu plus large que private : la classe elle-meme peut y accéder en interne et les objets du même package peuvent y accéder.
Ceci est aussi valable pour les classes définies sans modifier : dans ce cas elle ne peut être accédée qu'à l'intérieur du package.
Une classe ne peut avoir que deux modifiers possibles : public et sans modifier.
Une variable de classe (non instantiée et valable pour toutes les instances d'une classe) est définié par le modifier "static".
Il en va de même pour les méthodes de classe.
Exemple :
Le mot cle "final" sur un champs indique que la valeur ne peut pas être modifiée (donc read-only). C'est ainsi qu'on définit des constantes :
Le mot clé "final", lorsqu'il est défini au niveau d'une méthode, signifie que la méthode ne peut pas être redéfinie dans une sous-classe.
Le mot clé "final", lorsqu'il est défini au niveau d'une classe, signifie que la classe ne peut pas avoir de sous-classe.
Le mot clé "abstract" devant une méthode signifie que la méthode doit être redéfinie dans la sous-classe.
Le mot clé "abstract" devant une classe signifie que la classe ne peut être instantiée. Il faut définir une sous-classe.
Remarque : le mot clé abstract est optionnel pour les méthodes d'interface. Ces méthodes sont abstract implicitement.
Une classe peut hériter des champs et des méthodes d'une autre classe en utilisant le mot clé "extends".
Une sous-classe hérite des membres public et protected mais elle n'hérite pas des membres private de la classe parent.
Une classe peut hériter d'une classe au plus. Pas défaut, tout classe hérite de la classe Object. Comme l'héritage multiple n'existe pas, on utilise les interfaces à la place.
Le constructeur n'est pas hérité car ce n'est pas un membre de classe.
Le constructeur peut être redéfini au niveau d'une sous-classe. Dans ce cas, le code du parent n'est pas exécuté.
Pour exécuter le code du constructeur parent, il faut appeller la méthode super(arguments) obligatoirement sur la première ligne.
Important : Si un constructeur dans la sous-classe ne fait pas appel à super, alors Java insère automatiquement un appel à super sans argument, et si ce constructeur n'existe pas, il y a une erreur à la compilation.
Il est possible dans une sous-classe :
Il est conseillé d'utiliser l'annotation @override lorsqu'on redéfinit une méthode. On a ainsi moins de chance de se tromper de signature.
Il est possible de redéfinir une méthode de classe. Dans ce cas, elle ne sera valable que dans la sous-classe. On parle de hidding et non pas overriding.
Casting :
Un objet peut être affecté à une variable de la super classe mais pas l'inverse.
Par défaut, une classe qui n'hérite d'aucune classe va hériter de la classe Object.
Si une classe hérite d'une autre classe, elle héritera de déscendance, de la classe Object.
La classe java.lang.Object possède les méthodes suivantes, qu'il est possible de surcharger (override) :
Il est possible de redéfinir ces méthodes.
La classe String redéfinit déjà la méthode equals.
D'autres méthodes sont liées aux Threads et ne peuvent pas être modifiées (override) :
Une classe abstraite est une classe qui ne peut pas être instanciée.
Une méthode abstraite est une méthode déclarée uniquement avec sa signature et qui doit être redéfinie dans la sous-classe. Elle définit en quelque sorte un "contrat de classe".
Une méthode abstraite doit toujours être définie dans une classe abstraite, mais une classe abstraite peut ne pas avoir de méthodes abstraites.
Une classe abstraite peut avoir pour enfant une classe abstraite.
Différence Classes abstraites / Interfaces :
Une interface peut avoir des champs, mais ils doivent être obligatoirement public static final
Une interface peut avoir des méthodes, mais elles doivent être obligatoirement public
On utilise donc une classe abstraite lorsque :
Une interface est un type référence à l'instar d'une classe.
Une interface peut contenir :
Par défaut, toutes les méthodes sont implicitement public, donc le mot clé public est optionnel.
L'interface définit un contrat pour la classe qui l'impémente (mot clé implements).
Une interface peut hériter d'une interface (mot clé extends) et même de plusieurs interfaces.
Une interface peut être :
Une classe peut hériter des méthodes et champs static de zéro ou plusieurs interfaces.
Utilisation d'une interface comme un type
Un object o qui implémente l'interface i peut être manipulé comme un objet de type i.
Evolution d'une interface : default méthodes
Une premiere version d'interface se présente comme suit :
On veut ajouter une troisieme methode alors que l'interface est déjà largement utilisé :
La default methode peut être implémentée (nouveaux programmes) ou pas (anciens programmes).
Cas Particulier : si une classe implémente deux interfaces qui ont chacunes une méthode de même nom avec la même signature, alors la classe doit redéfinir la méthode en question.
Le polymorphistme consiste à écrire une méthode de plusieurs manières avec des signatures différentes (différence entre nombre et type d'arguments).
Polymorphisme d'héritage :
En redéfinissant une méthde dans une sous-classe, on peut spécialiser le comportement d'une méthode. Ainsi, selon que l'on sera dans la super classe ou la sous-classe, le résultat de l'appel sera différent.
L'encapsulation a pour but de cacher les champs d'une classe et permettre des modifications uniquement au travers de classes.
Un des aventages est de permettre d'établir des droits en lecture / écriture.
Une nested class est une classe définie à l'intérieur d'une autre. On les appelle aussi "helper class".
On distingue deux types de nested class :
Les nested class peuvent être déclarées public, private, protected ou package-private. Alors que la outer class ne peut être que public ou package private.
Utilisation d'une static class :
Utilisation d'une inner class :
Intéret d'utiliser une nested class : regrouper le code au même endroit si cette classe n'est utilisée qu'à un seul endroit. On peut aussi augmenter l'encapsulation car la inner class peut accéder aux champs private de la outer class.
Priorité des variables
On parle de shadowing lorsqu'une variable de inner class éclipse une variable de outer class.
Exemple :
Local classes versus anonymous classes :
Une Inner Class peut être une "local class" ou une "anonymous class".
Une local class est ce que l'on a vu jusqu'à présent.
Une anonymous class est différence dans sa déclaration : on mixe la déclaration avec l'opérateur new :
Dans l'exemple ci-dessus, l'objet frenchGreeting implémente l'interface HelloWorld mais ne possède pas de classe à proprement parler.
Une "anonymous class" doit implémenter une interface ou hériter d'une classe.
Les "anonymous class" se rencontrent souvent dans les api des interfaces graphiques, comme dans l'exemple ci-dessous :
Une énumération est un type qui permet à une variable de prendre plusieurs valeurs prédéfinies qui sont des constantes.
Parce que les valeurs sont des constantes, elles doivent être écrites en majuscule.
Tous les types enum sont des classes qui étende java.lang.Enum. On trouve y la méthode statique values() qui liste toutes les valeurs définies dans l'enum par ordre de déclaration.
Important : Un type enum peut donc avoir un constructeur avec des parametres ainsi que des méthodes. Il peut même avoir une méthode main.
Le constructeur d'un enum doit être private ou package private.
Les modifieurs d'accès
Modifier
Classe
Package
Sous-Classe
Tout le monde
public
X
X
X
X
protected
X
X
X
-
nom défini
X
X
-
-
private
X
-
-
-
Les modifieurs static et final
Le modifier abstract
L'héritage
La classe Object
Les classes abstraites
Les interfaces
Le polymorphisme
Polymorphisme paramétrique :
L'encapsulation
Les nested classes
Les énumérations