Instanciation dynamique

Difficulté Facile
Note
Thématiques
Mis à jour le lundi 7 janvier 2013

Nous allons voir une petite partie de la puissance de cette classe (pour l'instant). Dans un premier temps, créez un nouveau projet avec une méthode main ainsi qu'une classe correspondant au diagramme en figure suivante.

Classe Paire
Classe Paire

Voici son code Java :

public class Paire {
  private String valeur1, valeur2;

  public Paire(){
    this.valeur1 = null;
    this.valeur2 = null;
    System.out.println("Instanciation !");
  }

  public Paire(String val1, String val2){
    this.valeur1 = val1;
    this.valeur2 = val2;
    System.out.println("Instanciation avec des paramètres !");
  }

  public String toString(){
    return  "Je suis un objet qui a pour valeur : " + this.valeur1 +  " - " + this.valeur2;
  }

  public String getValeur1() {
    return valeur1;
  }
 
  public void setValeur1(String valeur1) {
    this.valeur1 = valeur1;
  }

  public String getValeur2() {
    return valeur2;
  }

  public void setValeur2(String valeur2) {
    this.valeur2 = valeur2;
  }
}

Le but du jeu consiste à créer un objet Paire sans utiliser l'opérateur new.

Pour instancier un nouvel objet Paire, commençons par récupérer ses constructeurs. Ensuite, nous préparons un tableau contenant les données à insérer, puis invoquons la méthode toString().

Regardez comment procéder ; attention, il y a moult exceptions :

public static void main(String[] args) {                                
  String nom = Paire.class.getName();                
  try {
    //On crée un objet Class
    Class cl = Class.forName(nom);
    //Nouvelle instance de la classe Paire
    Object o = cl.newInstance();

    //On crée les paramètres du constructeur
    Class[] types = new Class[]{String.class, String.class};
    //On récupère le constructeur avec les deux paramètres
    Constructor ct = cl.getConstructor(types);

    //On instancie l'objet avec le constructeur surchargé !
    Object o2 = ct.newInstance(new String[]{"valeur 1 ", "valeur 2"} );

  } catch (SecurityException e) {
    e.printStackTrace();
  } catch (IllegalArgumentException e) {
    e.printStackTrace();
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  } catch (InstantiationException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  }
}

Et le résultat donne la figure suivante.

Instanciation dynamique
Instanciation dynamique

Nous pouvons maintenant appeler la méthode toString() du deuxième objet… Oh et puis soyons fous, appelons-la sur les deux :

public static void main(String[] args) {                                
  String nom = Paire.class.getName();
  try {
    //On crée un objet Class
    Class cl = Class.forName(nom);
    //Nouvelle instance de la classe Paire
    Object o = cl.newInstance();
                                
    //On crée les paramètres du constructeur
    Class[] types = new Class[]{String.class, String.class};
    //On récupère le constructeur avec les deux paramètres
    Constructor ct = cl.getConstructor(types);      
    //On instancie l'objet avec le constructeur surchargé !
    Object o2 = ct.newInstance(new String[]{"valeur 1 ", "valeur 2"} );

    //On va chercher la méthode toString, elle n'a aucun paramètre
    Method m = cl.getMethod("toString", null);
    //La méthode invoke exécute la méthode sur l'objet passé en paramètre
    //Pas de paramètre, donc null en deuxième paramètre de la méthode invoke !
                                
    System.out.println("----------------------------------------");
    System.out.println("Méthode " + m.getName() + " sur o2: " +m.invoke(o2, null));
    System.out.println("Méthode " + m.getName() + " sur o: " +m.invoke(o, null));
                                
  } catch (SecurityException e) {
    e.printStackTrace();
  } catch (IllegalArgumentException e) {
    e.printStackTrace();
  } catch (ClassNotFoundException e) {
    e.printStackTrace();
  } catch (InstantiationException e) {
    e.printStackTrace();
  } catch (IllegalAccessException e) {
    e.printStackTrace();
  } catch (NoSuchMethodException e) {
    e.printStackTrace();
  } catch (InvocationTargetException e) {
    e.printStackTrace();
  }
}

Et le résultat en figure suivante.

Invocation dynamique de méthodes
Invocation dynamique de méthodes

Voilà : nous venons de créer deux instances d'une classe sans passer par l'opérateur new. Mieux encore, nous avons pu appeler une méthode de nos instances ! Je ne vais pas m'attarder sur ce sujet, mais gardez en tête que cette façon de faire, quoique très lourde, pourrait vous être utile.

Sachez que certains frameworks (ensemble d'objets offrant des fonctionnalités pour développer) utilisent la réflexivité afin d'instancier leurs objets (je pense notamment à des frameworks basés sur des fichiers de configuration XML tels que Hibernate, Struts, Spring…). L'utilité de ceci vous semble-t-elle évidente ? Même si vous ne savez pas les utiliser, peut-être avez-vous déjà entendu parler de ces frameworks Java.

Maintenant, vous n'allez pas utiliser ce genre de technique tous les jours. Cependant, il est possible que vous ayez besoin, pour une raison quelconque, de stocker le nom d'une classe Java dans une base de données afin, justement, de pouvoir l'utiliser plus tard. Dans ce cas, lorsque votre base de données vous fournira le nom de la classe en question, vous pourrez la manipuler dynamiquement.

  • Lorsque votre JVM interprète votre programme, elle crée automatiquement un objet Class pour chaque classe chargée.

  • Avec un tel objet, vous pouvez connaître absolument tout sur votre classe.

  • L'objet Class utilise des sous-objets tels que Method, Field et Constructor qui permettent de travailler avec vos différents objets ainsi qu'avec ceux présents dans Java.

  • Grâce à cet objet, vous pouvez créer des instances de vos classes Java sans utiliser new.

J'espère que cette partie vous a plu et que vous avez appris plein de bonne choses !
J'ai volontairement omis de parler des flux et des threads dans cette partie. Je préfère avoir des cas bien concrets à vous soumettre pour ça...

Bon : je sais que beaucoup d'entre vous l'attendent avec impatience, alors voici la partie sur la programmation événementielle !

L'auteur