t
t
t
t
t t   13) Création de fenêtres & d'Applets
tttt
t
carrea) Préface carreb) Avant-propos carre1) Introduction sur les &laqo; objets » carre2) Tout est &laqo; objet » carre3) Contrôle du flux du programme carre4) Initialization & Cleanup carre5) Cacher l'implémentation carre6) Réutiliser les classes carre7) Polymorphisme carre8) Interfaces & classes internes carre9) Stockage des objets carre10) Error Handling with Exceptions carre11) Le système d’E/S de Java carre12) Identification dynamique de type 13) Création de fenêtres & d'Applets carre14) Les &laqo; Threads » multiples carre15) Informatique distribuée carreA) Passage et retour d'objets carreB) L'Interface Java Natif (JNI) carreC) Conseils pour une programation stylée en Java carreD) Resources
Texte original t Traducteur : P. Boite
t
t
///
Ce chapitre contient 14 pages
1 2 3 4 5 6 7 8 9 10 11 12 13 14
\\\
t t t
t t t
t
t t t

Visual programming
and Beans

t

Programmation visuelle et Beans

t t t
So far in this book you’ve seen how valuable Java is for creating reusable pieces of code. The “most reusable” unit of code has been the class, since it comprises a cohesive unit of characteristics (fields) and behaviors (methods) that can be reused either directly via composition or through inheritance. t Jusqu'ici, dans ce livre, nous avons vu que Java permet de créer des morceaux de code réutilisables. L'unité de code la plus réutilisable est la classe, car elle contient un ensemble cohérent de caractéristiques (champs) et comportements (méthodes) qui peuvent être réutilisées soit directement par combinaison, soit par héritage.
t t t
Inheritance and polymorphism are essential parts of object-oriented programming, but in the majority of cases when you’re putting together an application, what you really want is components that do exactly what you need. You’d like to drop these parts into your design like the electronic engineer puts together chips on a circuit board. It seems, too, that there should be some way to accelerate this “modular assembly” style of programming. t L'héritage et le polymorphisme sont des éléments essentiels de la programmation orientée objet, mais dans la majorité des cas, lorsqu'on bâtit une application, en fait on désire disposer de composants qui font exactement ce qu'on veut. On aimerait placer ces éléments dans notre conception comme l'ingénieur électronicien qui assemble des puces sur un circuit. On sent bien qu'il devrait y avoir une façon d'accélérer ce style de programmation modulaire.
t t t
“Visual programming” first became successful—very successful—with Microsoft’s Visual Basic (VB), followed by a second-generation design in Borland’s Delphi (the primary inspiration for the JavaBeans design). With these programming tools the components are represented visually, which makes sense since they usually display some kind of visual component such as a button or a text field. The visual representation, in fact, is often exactly the way the component will look in the running program. So part of the process of visual programming involves dragging a component from a palette and dropping it onto your form. The application builder tool writes code as you do this, and that code will cause the component to be created in the running program. t La programmation visuelle est devenue très populaire d'abord avec le Visual Basic (VB) de Microsoft, ensuite avec une seconde génération d'outils, avec Delphi de Borland (l'inspiration principale de la conception des JavaBeans). Avec ces outils de programmation, les composants sont représentés visuellement, ce qui est logique car ils affichent d'habitude un composant visuel tel qu'un bouton ou un champ de texte. La représentation visuelle est en fait souvent exactement l'aspect du composant lorsque le programme tournera. Une partie du processus de programmation visuelle consiste à faire glisser un composant d'une palette pour le déposer dans un formulaire. Pendant qu'on fait cette opération, l'outil de construction d'applications génère du code, et ce code entraînera la création du composant lors de l'exécution du programme.
t t t
Simply dropping the component onto a form is usually not enough to complete the program. Often, you must change the characteristics of a component, such as what color it is, what text is on it, what database it’s connected to, etc. Characteristics that can be modified at design time are referred to as properties. You can manipulate the properties of your component inside the application builder tool, and when you create the program this configuration data is saved so that it can be rejuvenated when the program is started. t Le simple fait de déposer des composants dans un formulaire ne suffit généralement pas à compléter le programme. Il faut souvent modifier les caractéristiques d'un composant, telles que sa couleur, son texte, à quelle base de données il est connecté, et cetera. Des caractéristiques pouvant être modifiées au moment de la conception s'appellent des propriétés [properties]. On peut manipuler les propriétés du composant dans l'outil de construction d'applications, et ces données de configuration sont sauvegardées lors de la construction du programme, de sorte qu'elles puissent être régénérées lors de son exécution.
t t t
By now you’re probably used to the idea that an object is more than characteristics; it’s also a set of behaviors. At design-time, the behaviors of a visual component are partially represented by events, meaning “Here’s something that can happen to the component.” Ordinarily, you decide what you want to happen when an event occurs by tying code to that event. t Vous êtes probablement maintenant habitués à l'idée qu'un objet est plus que des caractéristiques ; c'est aussi un ensemble de comportements. A la conception, les comportements d'un composant visuel sont partiellement représentés par des événements [events], signifiant : «ceci peut arriver à ce composant». En général on décide de ce qui se passera lorsqu'un événement apparaît en liant du code à cet événement.
t t t
Here’s the critical part: the application builder tool uses reflection to dynamically interrogate the component and find out which properties and events the component supports. Once it knows what they are, it can display the properties and allow you to change those (saving the state when you build the program), and also display the events. In general, you do something like double-clicking on an event and the application builder tool creates a code body and ties it to that particular event. All you have to do at that point is write the code that executes when the event occurs. t C'est ici que se trouve le point critique du sujet : l'outil de construction d'applications utilise la réflexion pour interroger dynamiquement le composant et découvrir quelles propriétés et événements le composant accepte. Une fois connues, il peut afficher ces propriétés et en permettre la modification (tout en sauvegardant l'état lors de la construction du programme), et afficher également les événements. En général, on double-clique sur un événement et l'outil crée la structure du code relié à cet événement. Tout ce qu'il reste à faire est d'écrire le code qui s'exécute lorsque cet événement arrive.
t t t
All this adds up to a lot of work that’s done for you by the application builder tool. As a result you can focus on what the program looks like and what it is supposed to do, and rely on the application builder tool to manage the connection details for you. The reason that visual programming tools have been so successful is that they dramatically speed up the process of building an application—certainly the user interface, but often other portions of the application as well.
t Tout ceci fait qu'une bonne partie du travail est faite par l'outil de construction d'applications. On peut alors se concentrer sur l'aspect du programme et ce qu'il est supposé faire, et s'appuyer sur l'outil pour s'occuper du détail des connexions. La raison pour laquelle les outils de programmation visuels on autant de succès est qu'ils accélèrent fortement le processus de construction d'une application, l'interface utilisateur à coup sûr, mais également d'autres parties de l'application.
t t t

What is a Bean?

t

Qu'est-ce qu'un Bean ?

t t t
After the dust settles, then, a component is really just a block of code, typically embodied in a class. The key issue is the ability for the application builder tool to discover the properties and events for that component. To create a VB component, the programmer had to write a fairly complicated piece of code following certain conventions to expose the properties and events. Delphi was a second-generation visual programming tool and the language was actively designed around visual programming so it is much easier to create a visual component. However, Java has brought the creation of visual components to its most advanced state with JavaBeans, because a Bean is just a class. You don’t have to write any extra code or use special language extensions in order to make something a Bean. The only thing you need to do, in fact, is slightly modify the way that you name your methods. It is the method name that tells the application builder tool whether this is a property, an event, or just an ordinary method. t Une fois la poussière retombée, un composant est uniquement un bloc de code, normalement intégré dans une classe. La clé du système est la capacité du constructeur d'applications de découvrir les propriétés et événements de ce composant. Pour créer un composant VB, le programmeur devait écrire un bout de code assez compliqué, en suivant certaines conventions pour exposer les propriétés et événements. Delphi est un outil de programmation visuelle de seconde génération, pour lequel il est beaucoup plus facile de créer un composant visuel. Java de son côté a porté la création de composants visuels à son état le plus avancé, avec les JavaBeans, car un Bean est tout simplement une classe. Il n'y a pas besoin d'écrire de code supplémentaire ou d'utiliser des extensions particulières du langage pour transformer quelque chose en Bean. La seule chose à faire, en fait, est de modifier légèrement la façon de nommer les méthodes. C'est le nom de la méthode qui dit au constructeur d'applications s'il s'agit d'une propriété, d'un événement, ou simplement une méthode ordinaire.
t t t
In the Java documentation, this naming convention is mistakenly termed a “design pattern.” This is unfortunate, since design patterns (see Thinking in Patterns with Java, downloadable at www.BruceEckel.com) are challenging enough without this sort of confusion. It’s not a design pattern, it’s just a naming convention and it’s fairly simple: t Dans la documentation Java, cette convention de nommage est par erreur désignée comme un modèle de conception [design pattern]. Ceci est maladroit, car les modèles de conception (voir Thinking in Patterns with Java, téléchargeable à www.BruceEckel.com) sont suffisamment difficiles à comprendre sans ajouter ce genre de confusions. Ce n'est pas un modèle de conception, c'est uniquement une convention de nommage assez simple :
t t t
  1. For a property named xxx, you typically create two methods: getXxx( ) and setXxx( ). Note that the first letter after “get” or “set” is automatically lowercased to produce the property name. The type produced by the “get” method is the same as the type of the argument to the “set” method. The name of the property and the type for the “get” and “set” are not related.
  2. For a boolean property, you can use the “get” and “set” approach above, but you can also use “is” instead of “get.”
  3. Ordinary methods of the Bean don’t conform to the above naming convention, but they’re public.
  4. For events, you use the Swing “listener” approach. It’s exactly the same as you’ve been seeing: addFooBarListener(FooBarListener) and removeFooBarListener(FooBarListener) to handle a FooBarEvent. Most of the time the built-in events and listeners will satisfy your needs, but you can also create your own events and listener interfaces.
t
  1. Pour une propriété nommée xxx, on crée deux méthodes : getXxx() et setXxx(). Remarquons que la première lettre après get ou set est transformée automatiquement en minuscule pour obtenir le nom de la propriété. Le type fourni par la méthode get est le même que le type de l'argument de la méthode set. Le nom de la propriété et le type pour les méthodes get et set ne sont pas liés.
  2. Pour une propriété de type boolean, on peut utiliser les méthodes get et set comme ci-dessus, ou utiliser is au lieu de get.
  3. Les méthodes ordinaires du Bean ne suivent pas la convention de nommage ci-dessus, mais elles sont public.
  4. Pour les événements, on utilise la technique Swing du listener. C'est exactement la même chose que ce qu'on a déjà vu : addFooBarListener(FooBarListener) et removeFooBarListener(FooBarListener) pour gérer un FooBarEvent. La plupart du temps, les événements intégrés satisfont les besoins, mais on peut créer ses propres événements et interfaces listeners.
t t t
Point 1 above answers a question about something you might have noticed when looking at older code vs. newer code: a number of method names have had small, apparently meaningless name changes. Now you can see that most of those changes had to do with adapting to the “get” and “set” naming conventions in order to make that particular component into a Bean. t Le point 1 ci-dessus répond à la question que vous vous êtes peut-être posée en comparant un ancien et un nouveau code : un certain nombre de méthodes ont subi de petits changements de noms, apparemment sans raison. On voit maintenant que la plupart de ces changements avaient pour but de s'adapter aux conventions de nommage get et set de manière à transformer les composants en Beans.
t t t
We can use these guidelines to create a simple Bean: t On peut utiliser ces règles pour créer un Bean simple :
t t t
//: frogbean:Frog.java // A trivial JavaBean. package frogbean; import java.awt.*; import java.awt.event.*; class Spots {} public class Frog { private int jumps; private Color color; private Spots spots; private boolean jmpr; public int getJumps() { return jumps; } public void setJumps(int newJumps) { jumps = newJumps; } public Color getColor() { return color; } public void setColor(Color newColor) { color = newColor; } public Spots getSpots() { return spots; } public void setSpots(Spots newSpots) { spots = newSpots; } public boolean isJumper() { return jmpr; } public void setJumper(boolean j) { jmpr = j; } public void addActionListener( ActionListener l) { //... } public void removeActionListener( ActionListener l) { // ... } public void addKeyListener(KeyListener l) { // ... } public void removeKeyListener(KeyListener l) { // ... } // An "ordinary" public method: public void croak() { System.out.println("Ribbet!"); } } ///:~ t
//: frogbean:Frog.java
// Un JavaBean trivial.
package frogbean;
import java.awt.*;
import java.awt.event.*;

class Spots {}

public class Frog {
  private int jumps;
  private Color color;
  private Spots spots;
  private boolean jmpr;
  public int getJumps() { return jumps; }
  public void setJumps(int newJumps) {
    jumps = newJumps;
  }
  public Color getColor() { return color; }
  public void setColor(Color newColor) {
    color = newColor;
  }
  public Spots getSpots() { return spots; }
  public void setSpots(Spots newSpots) {
    spots = newSpots;
  }
  public boolean isJumper() { return jmpr; }
  public void setJumper(boolean j) { jmpr = j; }
  public void addActionListener(
      ActionListener l) {
    //...
  }
  public void removeActionListener(
      ActionListener l) {
    // ...
  }
  public void addKeyListener(KeyListener l) {
    // ...
  }
  public void removeKeyListener(KeyListener l) {
    // ...
  }
  // Une méthode public "ordinaire" :
  public void croak() {
    System.out.println("Ribbet!");
  }
} ///:~
t t t
First, you can see that it’s just a class. Usually, all your fields will be private, and accessible only through methods. Following the naming convention, the properties are jumps, color, spots, and jumper (notice the case change of the first letter in the property name). Although the name of the internal identifier is the same as the name of the property in the first three cases, in jumper you can see that the property name does not force you to use any particular identifier for internal variables (or, indeed, to even have any internal variables for that property). t Tout d'abord, on voit qu'il s'agit d'une simple classe. En général, tous les champs seront private, et accessibles uniquement à l'aide des méthodes. En suivant la convention de nommage, les propriétés sont jumps, color, spots et jumper (remarquons le passage à la minuscule pour la première lettre du nom de la propriété). Bien que le nom de l'identificateur interne soit le même que le nom de la propriété dans les trois premiers cas, dans jumper on peut voir que le nom de la propriété n'oblige pas à utiliser un identificateur particulier pour les variables internes (ou même, en fait, d'avoir des variable internes pour cette propriété).
t t t
The events this Bean handles are ActionEvent and KeyEvent, based on the naming of the “add” and “remove” methods for the associated listener. Finally, you can see that the ordinary method croak( ) is still part of the Bean simply because it’s a public method, not because it conforms to any naming scheme.
t Les événements gérés par ce Bean sont ActionEvent et KeyEvent, basés sur le nom des méthodes add et remove pour le listener associé. Enfin on remarquera que la méthode ordinaire croak() fait toujours partie du Bean simplement parce qu'il s'agit d'une méthode public, et non parce qu'elle se conforme à une quelconque convention de nommage.
t t t

Extracting BeanInfo
with the Introspector

t

Extraction des informations sur les Beans [BeanInfo] à l'aide de l'introspecteur [Introspector]

t t t
One of the most critical parts of the Bean scheme occurs when you drag a Bean off a palette and plop it onto a form. The application builder tool must be able to create the Bean (which it can do if there’s a default constructor) and then, without access to the Bean’s source code, extract all the necessary information to create the property sheet and event handlers. t L'un des points critiques du système des Beans est le moment où on fait glisser un bean d'une palette pour le déposer dans un formulaire. L'outil de construction d'applications doit être capable de créer le Bean (il y arrive s'il existe un constructeur par défaut) et, sans accéder au code source du Bean, extraire toutes les informations nécessaires à la création de la feuille de propriétés et de traitement d'événements.
t t t
Part of the solution is already evident from the end of Chapter 12: Java reflection allows all the methods of an anonymous class to be discovered. This is perfect for solving the Bean problem without requiring you to use any extra language keywords like those required in other visual programming languages. In fact, one of the prime reasons that reflection was added to Java was to support Beans (although reflection also supports object serialization and remote method invocation). So you might expect that the creator of the application builder tool would have to reflect each Bean and hunt through its methods to find the properties and events for that Bean. t Une partie de la solution est déjà évidente depuis la fin du Chapitre 12 : la réflexion Java permet de découvrir toutes les méthodes d'une classe anonyme. Ceci est parfait pour résoudre le problème des Beans, sans avoir accès à des mots clés du langage spéciaux, comme ceux utilisés dans d'autres langages de programmation visuelle. En fait, une des raisons principales d'inclure la réflexion dans Java était de permettre les Beans (bien que la réflexion serve aussi à la sérialisation des objets et à l'invocation de méthodes à distance [RMI : remote method invocation]). On pourrait donc s'attendre à ce qu'un outil de construction d'applications doive appliquer la réflexion à chaque Bean et à fureter dans ses méthodes pour trouver les propriétés et événements de ce Bean.
t t t
This is certainly possible, but the Java designers wanted to provide a standard tool, not only to make Beans simpler to use but also to provide a standard gateway to the creation of more complex Beans. This tool is the Introspector class, and the most important method in this class is the static getBeanInfo( ). You pass a Class reference to this method and it fully interrogates that class and returns a BeanInfo object that you can then dissect to find properties, methods, and events. t Ceci serait certainement possible, mais les concepteurs du langage Java voulaient fournir un outil standard, non seulement pour rendre les Beans plus faciles à utiliser, mais aussi pour fournir une plate-forme standard pour la création de Beans plus complexes. Cet outil est la classe Introspector, la méthode la plus importante de cette classe est le static getBeanInfo(). On passe la référence d'une Class à cette méthode , elle l'interroge complètement et retourne un objet BeanInfo qu'on peut disséquer pour trouver les propriétés, méthodes et événements.
t t t
Usually you won’t care about any of this—you’ll probably get most of your Beans off the shelf from vendors, and you don’t need to know all the magic that’s going on underneath. You’ll simply drag your Beans onto your form, then configure their properties and write handlers for the events you’re interested in. However, it’s an interesting and educational exercise to use the Introspector to display information about a Bean, so here’s a tool that does it: t Vous n'aurez probablement pas à vous préoccuper de tout ceci, vous utiliserez probablement la plupart du temps des beans prêts à l'emploi, et vous n'aurez pas besoin de connaître toute la magie qui se cache là-dessous. Vous ferez simplement glisser vos Beans dans des formulaires, vous en configurerez les propriétés et vous écrirez des traitements pour les événements qui vous intéressent. Toutefois, c'est un exercice intéressant et pédagogique d'utiliser l'Introspector pour afficher les informations sur un Bean, et voici donc un outil qui le fait :
t t t
//: c13:BeanDumper.java // Introspecting a Bean. // <applet code=BeanDumper width=600 height=500> // </applet> import java.beans.*; import java.lang.reflect.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import com.bruceeckel.swing.*; public class BeanDumper extends JApplet { JTextField query = new JTextField(20); JTextArea results = new JTextArea(); public void prt(String s) { results.append(s + "\n"); } public void dump(Class bean){ results.setText(""); BeanInfo bi = null; try { bi = Introspector.getBeanInfo( bean, java.lang.Object.class); } catch(IntrospectionException e) { prt("Couldn't introspect " + bean.getName()); return; } PropertyDescriptor[] properties = bi.getPropertyDescriptors(); for(int i = 0; i < properties.length; i++) { Class p = properties[i].getPropertyType(); prt("Property type:\n " + p.getName() + "Property name:\n " + properties[i].getName()); Method readMethod = properties[i].getReadMethod(); if(readMethod != null) prt("Read method:\n " + readMethod); Method writeMethod = properties[i].getWriteMethod(); if(writeMethod != null) prt("Write method:\n " + writeMethod); prt("===================="); } prt("Public methods:"); MethodDescriptor[] methods = bi.getMethodDescriptors(); for(int i = 0; i < methods.length; i++) prt(methods[i].getMethod().toString()); prt("======================"); prt("Event support:"); EventSetDescriptor[] events = bi.getEventSetDescriptors(); for(int i = 0; i < events.length; i++) { prt("Listener type:\n " + events[i].getListenerType().getName()); Method[] lm = events[i].getListenerMethods(); for(int j = 0; j < lm.length; j++) prt("Listener method:\n " + lm[j].getName()); MethodDescriptor[] lmd = events[i].getListenerMethodDescriptors(); for(int j = 0; j < lmd.length; j++) prt("Method descriptor:\n " + lmd[j].getMethod()); Method addListener = events[i].getAddListenerMethod(); prt("Add Listener Method:\n " + addListener); Method removeListener = events[i].getRemoveListenerMethod(); prt("Remove Listener Method:\n " + removeListener); prt("===================="); } } class Dumper implements ActionListener { public void actionPerformed(ActionEvent e) { String name = query.getText(); Class c = null; try { c = Class.forName(name); } catch(ClassNotFoundException ex) { results.setText("Couldn't find " + name); return; } dump(c); } } public void init() { Container cp = getContentPane(); JPanel p = new JPanel(); p.setLayout(new FlowLayout()); p.add(new JLabel("Qualified bean name:")); p.add(query); cp.add(BorderLayout.NORTH, p); cp.add(new JScrollPane(results)); Dumper dmpr = new Dumper(); query.addActionListener(dmpr); query.setText("frogbean.Frog"); // Force evaluation dmpr.actionPerformed( new ActionEvent(dmpr, 0, "")); } public static void main(String[] args) { Console.run(new BeanDumper(), 600, 500); } } ///:~ t
//: c13:BeanDumper.java
// Introspection d'un Bean.
// <applet code=BeanDumper width=600 height=500>
// </applet>
import java.beans.*;
import java.lang.reflect.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import com.bruceeckel.swing.*;

public class BeanDumper extends JApplet {
  JTextField query =
    new JTextField(20);
  JTextArea results = new JTextArea();
  public void prt(String s) {
    results.append(s + "\n");
  }
  public void dump(Class bean){
    results.setText("");
    BeanInfo bi = null;
    try {
      bi = Introspector.getBeanInfo(
        bean, java.lang.Object.class);
    } catch(IntrospectionException e) {
      prt("Couldn't introspect " +
        bean.getName());
      return;
    }
    PropertyDescriptor[] properties =
      bi.getPropertyDescriptors();
    for(int i = 0; i       Class p = properties[i].getPropertyType();
      prt("Property type:\n  " + p.getName() +
        "Property name:\n  " +
        properties[i].getName());
      Method readMethod =
        properties[i].getReadMethod();
      if(readMethod != null)
        prt("Read method:\n  " + readMethod);
      Method writeMethod =
        properties[i].getWriteMethod();
      if(writeMethod != null)
        prt("Write method:\n  " + writeMethod);
      prt("====================");
    }
    prt("Public methods:");
    MethodDescriptor[] methods =      bi.getMethodDescriptors();
    for(int i = 0; i       prt(methods[i].getMethod().toString());
    prt("======================");
    prt("Event support:");
    EventSetDescriptor[] events =
      bi.getEventSetDescriptors();
    for(int i = 0; i       prt("Listener type:\n  " +
        events[i].getListenerType().getName());
      Method[] lm =
        events[i].getListenerMethods();
      for(int j = 0; j         prt("Listener method:\n  " +
          lm[j].getName());
      MethodDescriptor[] lmd =
        events[i].getListenerMethodDescriptors();
      for(int j = 0; j         prt("Method descriptor:\n  " +
          lmd[j].getMethod());
      Method addListener =
        events[i].getAddListenerMethod();
      prt("Add Listener Method:\n  " +
          addListener);
      Method removeListener =        events[i].getRemoveListenerMethod();
      prt("Remove Listener Method:\n  " +
        removeListener);
      prt("====================");
    }
  }
  class Dumper implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      String name = query.getText();
      Class c = null;
      try {
        c = Class.forName(name);
      } catch(ClassNotFoundException ex) {
        results.setText("Couldn't find " + name);
        return;
      }
      dump(c);
    }
  }      
  public void init() {
    Container cp = getContentPane();
    JPanel p = new JPanel();
    p.setLayout(new FlowLayout());
    p.add(new JLabel("Qualified bean name:"));
    p.add(query);
    cp.add(BorderLayout.NORTH, p);
    cp.add(new JScrollPane(results));
    Dumper dmpr = new Dumper();
    query.addActionListener(dmpr);
    query.setText("frogbean.Frog");
    // Force evaluation
    dmpr.actionPerformed(
      new ActionEvent(dmpr, 0, ""));
  }
  public static void main(String[] args) {
    Console.run(new BeanDumper(), 600, 500);
  }
} ///:~
t t t
BeanDumper.dump( ) is the method that does all the work. First it tries to create a BeanInfo object, and if successful calls the methods of BeanInfo that produce information about properties, methods, and events. In Introspector.getBeanInfo( ), you’ll see there is a second argument. This tells the Introspector where to stop in the inheritance hierarchy. Here, it stops before it parses all the methods from Object, since we’re not interested in seeing those. t BeanDumper.dump() est la méthode qui fait tout le travail. Il essaie d'abord de créer un objet BeanInfo, et en cas de succès il appelle les méthodes de BeanInfo qui fournissent les informations sur les propriétés, méthodes et événements. Dans Introspector.getBeanInfo(), on voit qu'il y a un second argument. Celui-ci dit à l'Introspector où s'arrêter dans la hiérarchie d'héritage. Ici, il s'arrête avant d'analyser toutes les méthodes d'Object, parce qu'elles ne nous intéressent pas.
t t t
For properties, getPropertyDescriptors( ) returns an array of PropertyDescriptors. For each PropertyDescriptor you can call getPropertyType( ) to find the class of object that is passed in and out via the property methods. Then, for each property you can get its pseudonym (extracted from the method names) with getName( ), the method for reading with getReadMethod( ), and the method for writing with getWriteMethod( ). These last two methods return a Method object that can actually be used to invoke the corresponding method on the object (this is part of reflection). t Pour les propriétés, getPropertyDescriptors() renvoie un tableau de PropertyDescriptors. Pour chaque PropertyDescriptor, on peut appeler getPropertyType() pour connaître la classe d'un objet passé par les méthodes de propriétés. Ensuite, on peut obtenir le nom de chaque propriété (issu du nom des méthodes) à l'aide de getName(), la méthode pour la lire à l'aide de getReadMethod(), et la méthode pour la modifier à l'aide de getWriteMethod(). Ces deux dernières méthodes retournent un objet Method qui peut être utilisé pour appeler la méthode correspondante de l'objet (ceci fait partie de la réflexion).
t t t
For the public methods (including the property methods), getMethodDescriptors( ) returns an array of MethodDescriptors. For each one you can get the associated Method object and print its name. t Pour les méthodes public (y compris les méthodes des propriétés), getMethodDescriptors() renvoie un tableau de MethodDescriptors. Pour chacun de ces descripteurs, on peut obtenir l'objet Method associé, et imprimer son nom.
t t t
For the events, getEventSetDescriptors( ) returns an array of (what else?) EventSetDescriptors. Each of these can be queried to find out the class of the listener, the methods of that listener class, and the add- and remove-listener methods. The BeanDumper program prints out all of this information. t Pour les événements, getEventSetDescriptors() renvoie un tableau de (que pourrait-il renvoyer d'autre ?) EventSetDescriptors. Chacun de ces descripteurs peut être utilisé pour obtenir la classe du listener, les méthodes de cette classe listener, et les méthodes pour ajouter et enlever ce listener. Le programme BeanDumper imprime toutes ces informations.
t t t
Upon startup, the program forces the evaluation of frogbean.Frog. The output, after removing extra details that are unnecessary here, is: t Au démarrage, le programme force l'évaluation de frogbean.Frog. La sortie, après suppression de détails inutiles ici, est :
t t t
class name: Frog Property type: Color Property name: color Read method: public Color getColor() Write method: public void setColor(Color) ==================== Property type: Spots Property name: spots Read method: public Spots getSpots() Write method: public void setSpots(Spots) ==================== Property type: boolean Property name: jumper Read method: public boolean isJumper() Write method: public void setJumper(boolean) ==================== Property type: int Property name: jumps Read method: public int getJumps() Write method: public void setJumps(int) ==================== Public methods: public void setJumps(int) public void croak() public void removeActionListener(ActionListener) public void addActionListener(ActionListener) public int getJumps() public void setColor(Color) public void setSpots(Spots) public void setJumper(boolean) public boolean isJumper() public void addKeyListener(KeyListener) public Color getColor() public void removeKeyListener(KeyListener) public Spots getSpots() ====================== Event support: Listener type: KeyListener Listener method: keyTyped Listener method: keyPressed Listener method: keyReleased Method descriptor: public void keyTyped(KeyEvent) Method descriptor: public void keyPressed(KeyEvent) Method descriptor: public void keyReleased(KeyEvent) Add Listener Method: public void addKeyListener(KeyListener) Remove Listener Method: public void removeKeyListener(KeyListener) ==================== Listener type: ActionListener Listener method: actionPerformed Method descriptor: public void actionPerformed(ActionEvent) Add Listener Method: public void addActionListener(ActionListener) Remove Listener Method: public void removeActionListener(ActionListener) ==================== t
class name: Frog
Property type:
  Color
Property name:
  color
Read method:
  public Color getColor()
Write method:
  public void setColor(Color)
====================Property type:
  Spots
Property name:
  spots
Read method:
  public Spots getSpots()
Write method:
  public void setSpots(Spots)
====================Property type:
  boolean
Property name:
  jumper
Read method:
  public boolean isJumper()
Write method:
  public void setJumper(boolean)
====================Property type:
  int
Property name:
  jumps
Read method:
  public int getJumps()
Write method:
  public void setJumps(int)
====================Public methods:
public void setJumps(int)
public void croak()
public void removeActionListener(ActionListener)
public void addActionListener(ActionListener)
public int getJumps()
public void setColor(Color)
public void setSpots(Spots)
public void setJumper(boolean)
public boolean isJumper()
public void addKeyListener(KeyListener)
public Color getColor()
public void removeKeyListener(KeyListener)
public Spots getSpots()
======================Event support:
Listener type:
  KeyListener
Listener method:
  keyTyped
Listener method:
  keyPressed
Listener method:
  keyReleased
Method descriptor:
  public void keyTyped(KeyEvent)
Method descriptor:
  public void keyPressed(KeyEvent)
Method descriptor:
  public void keyReleased(KeyEvent)
Add Listener Method:
  public void addKeyListener(KeyListener)
Remove Listener Method:
  public void removeKeyListener(KeyListener)
====================Listener type:
  ActionListener
Listener method:
  actionPerformed
Method descriptor:
  public void actionPerformed(ActionEvent)
Add Listener Method:
  public void addActionListener(ActionListener)
Remove Listener Method:
  public void removeActionListener(ActionListener)
====================
t t t
t t t
t t
\\\
///
t t t
t
     
Sommaire Le site de Bruce Eckel