Object
, et en redescendant toute la hiérarchie jusqu'à la classe qu'elle charge, et pour toutes les classes nouvellement chargées :
Exemple 32. Exécution des blocs statiques lors du chargement d'une classe
public class Marin { // dans le fichier Marin.java public static long dateDeChargement = System.currentTimeMillis() ; // 1 static { System.out.println("Chargement de la classe Marin") ; // 2 } } public class Capitaine extends Marin { // dans le fichier Capitaine.java public static long dateDeChargement = System.currentTimeMillis() ; // 3 static { System.out.println("Chargement de la classe Capitaine") ; // 4 } }
Capitaine
déclenche les opérations statiques dans l'ordre de leur numérotation. À partir de la version 5 de Java ces blocs sont exécutés lors de la première instanciation de la classe
Capitaine
.
Marin
ci-dessous.
Exemple 33. Constructeur vide par défaut - 1
public class Marin { private String nom ; public String getNom() { return this.nom ; } public void setNom(String nom) { this.nom = nom ; } }
Marin marin = new Marin() ;Si l'on spécifie un constructeur dans cette classe, alors le constructeur vide par défaut n'est plus créé. Si l'on reprend notre exemple :
Exemple 34. Constructeur vide par défaut - 2
public class Marin { private String nom ; public Marin(String nom) { this.nom ; } public String getNom() { return this.nom ; } }
Marin marin = new Marin("Surcouf") ;Considérons l'exemple suivant.
Exemple 35. Constructeur vide par défaut - 3
public class Marin { // dans le fichier Marin.java private String nom ; // constructeur vide de la classe Marin public Marin() { nom = "indéfini" ; } } public class Capitaine extends Marin { // dans le fichier Capitaine.java private String grade public Capitaine(String grade) { this.grade = grade ; } }
Capitaine
:
Capitaine capitaine = new Capitaine("Capitaine de vaisseau") ;L'instanciation de l'objet
capitaine
déclenche les opérations suivantes :
Capitaine
est appelé ;
Marin
, qui initialise le champ
nom
;
Capitaine
initialise le champ
grade
.
Capitaine
.
Il est également possible pour un constructeur d'appeler explicitement un unique constructeur. Cet appel ne peut être que la première instruction de ce constructeur. Voyons cela sur un exemple.
Exemple 36. Appels explicites de constructeurs
public class Marin { // dans le fichier Marin.java private String nom ; public Marin(String nom) { this.nom = nom ; } } public class Capitaine extends Marin { // dans le fichier Capitaine.java private String grade public Capitaine(String nom, String grade) { super(nom) ; // appel du constructeur de la super classe this.grade = grade ; } public Capitaine(String grade) { this("indéfini", grade) ; // appel du constructeur de même classe } }
false
ou
null
suivant leur type ;
Exemple 37. Exemple d'une instanciation complexe
public class Marin { // dans le fichier Marin.java private long dateCreation = System.currentTimeMillis() ; { // ceci est un bloc non statique System.out.println(i) ; } private String nom ; public Marin() { this.nom = "indéfini" ; } public Marin(String nom) { this.nom = nom ; } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } } public class Capitaine extends Marin { // dans le fichier Capitaine.java private int grade ; private long dateCreation = System.currentTimeMillis() ; { // ceci est un bloc non statique System.out.println(i) ; } public Capitaine(String nom) { super(nom) ; } public Capitaine(String nom, int grade) { this(nom) ; this.grade = grade ; } }
Capitaine m = new Capitaine("Surcouf", 2) ;Les opérations s'enchaînent de la façon suivante :
(String, int)
de
Capitaine
;
(String)
de
Capitaine
;
(String)
de
Marin
;
dateCreation
de
Marin
;
Marin
;
(String)
de
Marin
;
dateCreation
de
Capitaine
;
Capitaine
;
(String)
de
Capitaine
;
(String, int)
de
Capitaine
.
final
.
finalize()
dans la classe
Object
,
détaillée ici, qui joue le rôle de callback avant que le
garbage collector
ne détruise un objet.
final
, alors il n'est pas possible de l'étendre. De nombreuses classes sont
final
dans l'API standard : c'est le cas de
String
, et de toutes les classes enveloppes des classes de base.
Il peut être utilisé de façon analogue sur une méthode. Une méthode déclarée
final
ne peut pas être surchargée par une méthode d'une classe qui étendrait la classe dans laquelle cette méthode est définie. Par exemple, les méthodes
wait()
de la classe
Object
sont finales, elles ne peuvent donc pas être surchargées.
Il peut être utilisé sur le champ d'une classe, statique ou non. Dans ce cas, une fois intialisé, ce champ ne pourra plus être modifié. Se pose alors la question, à quel moment peut-on, et doit-ont initialiser un champ
final
?
Un champ
static final
, doit être initialisé par un initialiseur de champ ou un bloc statique.
Un champ
final
(non statique) doit être initialisé par un initialiseur de champ, un bloc non statique, ou dans le constructeur.
Un champ
final
, statique ou non, ne peut pas être initialisé deux fois, une fois initialisé, il n'est plus possible de changer sa valeur.
Si un objet possède plusieurs constructeurs, et qu'il possède un champ
final
, alors l'initialisation de ce champ doit suivre le même processus, quel que soit le constructeur appelé. En particulier, si ce champ est initialisé dans un constructeur, alors tous les constructeurs doivent l'initialiser, y compris le constructeur par défaut.
Le mot-clé
final
peut être posé sur un paramètre reçu par une méthode. Dans ce cas, ce paramètre ne pourra être modifié.
Enfin, le mot-clé
final
peut être posé sur une variable définie dans une méthode. Dans ce cas, la valeur de cette variable ne pourra être modifiée.
Notons qu'une classe locale, anonyme ou non, peut accéder aux variables et paramètres définis dans la méthode dans laquelle elle-même a été définie, que si ceux-ci sont
final
.
Les règles d'utilisation des champs
final
sont complexes et subtiles. Heureusement les environnements de développement intégré sont là pour nous aider. Ils nous marquent les erreurs d'accès ou d'initialisation, et nous rappellent les règles à appliquer pour corriger nos erreurs.
String
StringBuffer
et
StringBuilder