1. JavaBeans

O JavaBeans é baseada em um modelo de componente que permite criar unidades de software chamadas de componentes. Componentes são auto-suficientes, as unidades de software reutilizável que pode ser visualmente montados em componentes compostos, applets, aplicativos e servlets utilizando ferramentas visuais construtor de aplicação. Componentes JavaBean são conhecidos como beans.

Sua característica principal é a reutilização de código, o pacote java.beans tem somente esta finalidade, contudo, um Java Bean é qualquer classe que siga as convenções de nomenclatura de métodos, construtores e comportamento. Estas convenções permitem a existência de ferramentas que podem utilizar e manipular os JavaBeans, tal como o Netbeans.

2. As convenções que definem a classe:
1. implemente a interface java.io.Serializable (que possibilita a persistência e restauração do estado do objeto da classe);
 2. possua um construtor sem argumentos;
 3. que as suas propriedades sejam acessíveis através de métodos get e set, seguindo um padrão de nomenclatura;
 4. possa conter qualquer método de tratamento de eventos.

3. Principais Conceitos usados no Modelo Java Beans

- Uma ferramenta visual descobre as propriedades, métodos e eventos de um Bean usando introspeção (introspection, ou "reflexão em componentes Bean").
- Introspeção: olhar dentro do Bean.
- Dizemos que as propriedades, métodos e eventos são expostos pelo Bean.
- Há duas formas de usar introspeção:

- Usando a API Reflection (que permite descobrir todos os métodos, atributos, etc. de uma classe), usa-se nomes padronizados de métodos para carregar a semântica desejada.

Introspecção e reflexão são propriedades de sistemas orientados a objetos que possibilitam a descoberta e alteração, em tempo de execução, de informações estruturais sobre um programa e objetos existentes neste.

Reflexão é a habilidade que um programa tem de examinar e alterar o seu próprio comportamento e estrutura em tempo de execução. Essa alteração de comportamento nos objetos, através da reflexão, acontece através do acesso e chamada aos métodos presentes em uma classe. Isso é, a capacidade de interagir com o objeto através de uma prévia análise de sua estrutura, a invocação dinâmica de métodos.

Introspecção é o comportamento da própria reflexão, ou seja, é a capacidade reflexiva que permite ao programa examinar a si próprio.

- Detalhando a informação de propriedades, métodos e eventos numa classe especial BeanInfo (Bean Information).

- Propriedades correspondem a atributos de aparência e de comportamento que podem ser mudados em tempo de Design.
Propriedades são expostas pelos Beans para que possam ser customizadas em tempo de design.

- A customização pode usar:

Editores de propriedades.

Customizadores de Beans (são wizards de customização mais sofisticados)

- Eventos, Propriedades e Métodos
JavaBeans divulgam um conjunto bem definido de eventos que produzem, e permitem que outros objetos registrem interesse na ocorrência destes eventos.
JavaBeans divulgam um conjunto bem definido de propriedades e métodos, permitindo que as propriedades sejam alteradas e os métodos sejam invocados.

3.1. Eventos:

Beans usam eventos para se comunicarem com outros Beans.

Um Bean que deseja receber eventos (Listener Bean) cadastra seu interesse junto ao Bean que dispara o evento (Source Bean).

As ferramentas visuais podem examinar o Bean e verificar quais eventos podem ser disparados (enviados) e quais eventos podem ser tratados (recebidos) pelo Bean.

JavaBeans usam o modelo de Eventos padrão do Java

Resumindo:

- Quem dispara um evento é um Event Source
- Um objeto interessado neste evento se cadastra junto ao Source e passa a ser um Listener
- Todos os listeners são avisados do evento (através de um callback feito pelo Source).
- O evento pode encapsular ou não informação especial para os listeners.
- Uma referência à fonte do evento (o objeto Source) sempre está disponível dentro do evento

O modelo de eventos no JavaBeans
Os eventos possíveis são:

- PropertyChangeEvent (para mudanças em Bound Properties)

- VetoableChangeEvent (para mudanças em Constrained Properties)

- Os Beans Source devem implementar alguns métodos dependendo dos eventos envolvidos

- Quem gera eventos PropertyChangeEvent deve implementar os seguintes métodos:

public void addPropertyChangeListener(PropertyChangeListener pcl);

public void removePropertyChangeListener(PropertyChangeListener pcl);

- Quem gera eventos VetoableChangeEvent deve implementar os seguintes métodos:

public void addVetoableChangeListener(VetoableChangeListener vcl);

public void removeVetoableChangeListener(VetoableChangeListener vcl);

- Quem gera eventos customizados deve implementar os seguintes métodos:

public void add<Custom>Listener(<Custom>Listener cl);

public void remove<Custom>Listener(<Custom>Listener cl);

- Os Beans Listener devem implementar a interface apropriada.

PropertyChangeListener

Deve implementar o método PropertyChange(PropertyChangeEvent e);

VetoableChangeListener

Deve implementar o método VetoableChange(VetoableChangeEvent e);

<Custom>Listener

Deve implementar o método public Xpto(<CustomEvent> e);


3.2. Propriedades

3.2.1. Simple Properties
Representam tipos de dados simples.
Podem ser nativos (int, String, ...) ou não.

Métodos devem se chamar get<NomePropriedade> e set<NomePropriedade>

public Color getCor();
public void setCor(Color cor);


Desta forma, a ferramenta visual infere que existe uma propriedade chamada "cor" que pode ser lida (get) e alterada (set).

Exemplo

import java.awt.*;
import java.io.Serializable;
public class SimpleBean extends Canvas implements Serializable {
// Construtor inicializa propriedades herdadas
public SimpleBean() {
setSize(60, 40);
setBackground(Color.red);
}
}
Canvas possui duas (ao menos) propriedades Size e background

3.2.2. Bound Properties  - Ligadas
Avisam a outros objetos que foram modificadas.
Bound Properties (Propriedades Amarradas) avisam outros objetos (Beans, por exemplo) de mudanças nos seus valores.
Uma mudança de valor gera um evento PropertyChangeEvent.
Listeners deste evento serão notificados da mudança.

Bound properties
Dispara um evento quando o seu valor é alterado.
O bean deve prover os seguintes métodos para adicionar e remover listeners.

void addPropertyChangeListener (PropertyChangeListener l);
void removePropertyChangeListener(PropertyChangeListenerl);

É suficiente chamar o método já existente.
A especificação JavaBeans 1.01 permite adicionar um listener para uma determinada propriedade

Conceitos Bound Properties
quando propriedade é alterada
evento é enviado a ouvidores (listeners)
Bean deve manter lista de ouvidores

classe PropertyChangeSupport
métodos para adicionar e remover ouvidores
método para enviar PropertyChangeEvent objeto aos ouvidores
quando propriedade é alterada Bean deve herdar esse classe ou usá-la como interna

interface PropertyChangeListener
método propertyChange
chamado quando propriedade é alterada
ouvidor deve implementar interface e método

3.2.3.  Constrained Properties - Restringidas
Cujos modificações são autorizadas por outros objetos.
Constrained Properties (Propriedades Restritas) são como Bound Properties mas os Listeners podem vetar a mudança.
Uma mudança aqui gera um evento VetoableChangeEvent

Constrained properties
Qualquer subscriber pode interromper a mudança gerando uma PropertyVetoException
Nesse caso, deve ser restaurado o valor original da propriedade.
Adição e remoção de listeners
void addVetoableChangeListener(VetoableChangeListener l);
void removeVetoableChangeListener(VetoableChangeListener l);

3.2.4. Indexed Properties - Indexadas
Descrevem valores múltiplos
Indexed Properties contêm um array de valores possíveis.
Métodos getter e setter são como para Simple Properties mas manipulam um array, ou recebem um índice a mais.


public String[] getEstados()
public String getEstados(int índice)
public void setEstados(String[] estados)
public void setEstados(int índice, String estado)

Propriedades:

Definem as características de um bean;

Possibilitam a configuração de um bean;

Podem ser lidas ou escritas através de métodos do bean;

Podem ser read-write, read-only ou write-only;

Podem ser simples ou com multiplos valores;

podem ser inativas ou ativas;

As ativas geram um evento quando o valor é modificado;

Não tem que ter o mesmo nome de um atributo nem estar relacionado a um único atributo.


Os métodos são divididos em duas categorias

Os métodos que retornam o valor dos atributos da classe beans são chamados de métodos getters, e os métodos que nos permitem alterar esse valor são chamados de métodos setters.

Métodos de Leitura:
Os métodos de leitura de propriedades devem seguir a seguinte convenção:

public TipoDaPropriedade getNomeDaPropriedade()

Como mostrado no código acima a propriedade chamada nomeDaPropriedade tem o método de acesso getNomeDaPropriedade().

Note que a primeira letra da propriedade deve ser minúscula enquanto a primeira letra depois do get deve ser em maiúscula, palavras compostas por mais de uma palavra, por regra, a primeira letra é maiúscula, porém, isso não se aplica a nome de variáveis, métodos, propriedades, etc, porque, a primeira letra de tais palavras são em minúscula, por regra.

A palavra TipoDaPropriedade deve ser substituida pelo tipo da propriedade. Para variáveis booleanas vale o mesmo conceito, mas, ao invés do get usamos a palavra is. No exemplo temos o acesso a propriedade propriedade2 que é booleana como:

public boolean isPropriedade2()

Observação: Você pode não definir um método de leitura para a variável. Se isto for feito você não permitirá o acesso a ela.

Métodos de escrita:
Os métodos de escrita permitem ao usuário do componente modificar o conteúdo da propriedade.
Ele segue a seguinte terminologia:

public void setNomeDaPropriedade(TipoDaPropriedade varName)

Nos métodos de escrita não há caso especial para variáveis booleanas que também podem ser modificadas através de métodos set.
Você pode não definir métodos de escrita para uma determinada variável, fazendo com que o usuário não seja capaz de modificar o conteúdo da propriedade.

Exemplos de métodos e, Class:

getName, getSuperClass, getInterfaces, getFields, getMethods, getConstructors, getPackage, isInterface e isPrimitive.

4. Introspecção e Reflexividade
Um JavaBean usa um padrão de codificação que permite que uma ferramenta de edição visual interaja com o componente e deduza e altere suas características (eventos, propriedades e métodos) em build-time ou run-time, exemplo, o Netbeans.

5. Persistência e Empacotamento
Capacidade de armazenar, recuperar ou transmitir um componente através de uma mídia digital (disco, conexão de rede, etc).

6. Componentes

Para transformar uma classe em um componente, é necessário adicionar funcionalidade e seguir sua convenção.
Componentes são interligados de modo a constituir uma aplicação.
Um componente é desenvolvido com um objetivo específico e não para uma aplicação específica.

Um modelo de componente é definido como um conjunto de classes e interfaces na forma de pacotes Java que deve ser usado em uma forma particular para isolar e encapsular um conjunto de funcionalidades.

6.1. Modelos de componentes.

Um modelo de componentes especifica como serão expostas as propriedades, métodos e eventos.
JavaBeans é um modelo de componentes para construção de aplicações de forma visual e Enterprise JavaBeans é um modelo de componentes para arquiteturas distribuídas.
Os modelos JavaBeans e Enterprise JavaBeans não são relacionados.
Enterprise JavaBeans não é uma extensão do JavaBeans.

7. Característica de um bean

Suporte para introspecção e customização.
Suporte para eventos na conexão entre componentes.
Suporte para propriedades.
Suporte para persistência.
Implementado como um arquivo jar.

Outra regra que um Bean deve seguir é a implementação da interface Serializable. A implementação desta interface fornece ao bean a propriedade chamada de persistência.

O conceito de persistência é permitir que o usuário faça uso do componente em um determinado momento e possa salvar o seu estado para o uso posterior partindo do mesmo ponto. A tecnologia que possibilita essa propriedade é a Serialização de Objetos. Esta tecnologia permite salvarmos o objeto em um fluxo para posterior recuperação. Quando houver a recuperação, o objeto deve se comportar como se fosse exatamente o mesmo de quando foi salvo.
A tecnologia de serialização de objetos é muito importante em Java pois permite a linguagem atividades complexas como computação distribuída e além de muitas outras funcionalidades interessantes.
Para sermos capazes de serializar objetos basta fazer a classe implementar a interface Serializable e nada mais.

JavaBeans são desenvolvidos param serem usados por terceiros (ou não). As ferramentas de desenvolvimento em Java são capazes de ler beans e prover a funcionalidade do componente para o usuário. Mas como as ferramentas são capazes de descobrir a funcionalidade de um Bean já que ele não é uma classe conhecida, ou seja, pode ser qualquer componente?
Para a realização desta tarefa, que chamamos instrospecção, é usada uma API disponível no Ambiente Runtime da plataforma Java, a Java Reflection API . Usando a funcionalidade desta API a ferramenta procura os métodos públicos do bean e faz a ligação dos métodos com as propriedades. Após a ferramenta ter obtido todas as informações que ela necessita sobre a classe então as propriedades e os métodos são disponibilizados para uso.
A instrospecção é realizada pela classe java.beans.Introspector que usa a Reflection API para descobrir as funcionalidades do bean por casamento de padrão. No entanto, alternativamente você pode definir as informações sobre o Bean em separado, em uma classe que implementa a interface BeanInfo.
É importante saber que um bean também pode implementar outros métodos que não aqueles que lêem ou gravam as propriedades. Esses métodos não diferem em nada de outros métodos de qualquer outra classe em Java.

8. Pacote Java.beans:

Contém classes relacionadas ao desenvolvimento de beans - componentes baseados na arquitetura JavaBeans:

Resumo da classe

Resumo exceções

Tipos Resumo de anotações


8.1. Descrição pacote java.beans

Contém classes relacionadas ao desenvolvimento de beans - componentes baseados na arquitetura JavaBeans. Algumas das classes são utilizados por beans enquanto são executados em um aplicativo.  Em particular, essas classes auxilia o editor de beans a criar uma interface de usuário que pode ser usada para personalizar o beans. Por exemplo, um beans pode conter uma propriedade de um tipo especial que um editor de beans pode não saber como lidar. Ao utilizar o PropertyEditor interface, um desenvolvedor de beans pode fornecer um editor para esse tipo especial.


Para minimizar os recursos utilizados por um bean, as classes usadas por editores de beans são carregados somente quando o beans está sendo editado. Eles não são necessários, enquanto o beans está sendo executado em um aplicativo e, portanto, não carregado. Esta informação é mantida no que é chamado de beans-info (ver BeanInfo ).

A menos que especificado, os valores nulos ou cadeias vazias não são parâmetros válidos para os métodos neste pacote. Você pode esperar para ver as exceções se esses parâmetros são usados.

Persistência a longo prazo

A partir de v1.4, o java.beans pacote fornece suporte para persistência a longo prazo - a leitura e a escrita de um bean como uma representação textual de seus valores de propriedade. Os valores de propriedade são tratados como beans, e são recursivamente lido ou escrito para capturar seu estado disponível publicamente. Esta abordagem é adequada para armazenamento de longo prazo, pois depende apenas de API pública, em vez da aplicação provável-à-mudar privado.


Nota: O esquema de persistência não pode automaticamente instanciar personalizados classes internas, como você pode usar para manipuladores de eventos. Ao utilizar o EventHandler classe em vez de classes internas para manipuladores de eventos personalizados, você pode evitar este problema.

Sabe ler e escrever beans em formato XML usando os XMLDecoder e XMLEncoder classes, respectivamente. Uma característica notável do esquema de persistência é que a leitura em um bean não requer nenhum conhecimento especial do beans.

Escrever um beans, por outro lado, às vezes requer conhecimento especial do tipo do beans. Se o estado do beans pode ser expressa usando apenas o construtor sem argumentos e métodos públicos getter e setter para as propriedades, nenhum conhecimento especial é necessário. Caso contrário, o beans requer um delegado persistência personalizado - um objeto que está encarregado de escrever beans de um tipo particular. Todas as classes previstas no JDK que descem da java.awt.Component, bem como todas as suas propriedades, automaticamente tem delegados de persistência.

Se você precisa (ou escolha) para fornecer um delegado de persistência para um beans, você pode fazê-lo pelo uso de um DefaultPersistenceDelegate instância ou criando sua própria subclasse de PersistenceDelegate . Se a única razão um beans precisa de um delegado persistência é porque você quer invoca o construtor do beans com valores de propriedade como argumentos, você pode criar delegado do beans com a persistência de um argumento DefaultPersistenceDelegate construtor. Caso contrário, você precisa implementar o delegado própria persistência, para os quais é provável que você precisa das seguintes classes:

PersistenceDelegate

A classe abstrata da qual todos os delegados de persistência descer. A subclasse deve usar seu conhecimento do tipo do beans para lhe prestar qualquer Statement s e Expression s são necessários para criar o bean e restaurar o seu estado.

Statement

Representa a invocação de um único método em um objeto. Inclui um conjunto de argumentos para o método.

Expression

Uma subclasse de Statement usado para métodos que retornam um valor.

Depois de criar um delegado de persistência, você registrá-lo usando o setPersistenceDelegate método de XMLEncoder .


Exemplo 1: 

Foi criado um bean chamado MeuBean cuja evento que irá modificar o nome da sua propriedade e depois será produzido uma notificação da alteração.


Neste exemplo vamos ouvir evento de alteração de propriedade do bean. Nós criamos um pequeno bean chamado MyBean , acrescenta atributos e getter / setter. Queremos saber ou para ser notificado quando o nome da propriedade do beans é alterado.

Primeiro temos a adicionar um PropertyChangeSupport campo para o bean, com esse objeto que vai disparar o evento de alteração de propriedade. Quando precisamos de ouvir a mudança, temos de criar uma implementação de um PropertyChangeListener . Neste exemplo vamos usar o MyBean classe como o ouvinte.

O PropertyChangeListener tem um método chamado propertyChange e dentro deste método, vamos implementar o código para obter o evento disparado pelo PropertyChangeSupport .


import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.io.Serializable;

public class MeuBean implements PropertyChangeListener, Serializable {

    private Long id;
    private String name;
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    public MeuBean() {
        pcs.addPropertyChangeListener(this);
    }

    /**
     * This method gets called when a bound property is changed.
     *
     * @param evt A PropertyChangeEvent object describing the event source and
     * the property that has changed.
     */
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("Name      = " + evt.getPropertyName());
        System.out.println("Old Value = " + evt.getOldValue());
        System.out.println("New Value = " + evt.getNewValue());
    }

    public static void main(String[] args) {
        MeuBean bean = new MeuBean();
        bean.setName("My Initial Value");
        bean.setName("My New Value");
        bean.setName("My Yet Another Value");
    }

    //~ --------------------------------------------- Bean's Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        String oldValue = this.name;
        this.name = name;

        //
        // Fires a property change event
        //
        pcs.firePropertyChange("name", oldValue, name);
    }

run:

Old Value = null
New Value = My Initial Value
Name      = name
Old Value = My Initial Value
New Value = My New Value
Name      = name
Old Value = My New Value
New Value = My Yet Another Value


Exemplo 2:

Um PropertyDescriptor descreve uma propriedade que um exportações Java Bean através de um par de métodos de acesso.

/**
 * BeanInfo: getPropertyDescriptors()
 */
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

public class Main2 {

    public static void main(String[] argv) throws Exception {
        BeanInfo bi = Introspector.getBeanInfo(MyBean.class);
        PropertyDescriptor[] pds = bi.getPropertyDescriptors();
        for (int i = 0; i < pds.length; i++) {
            String propName = pds[i].getDisplayName();
            System.out.println(propName);
        }
    }
}

class MyBean {

    public String getProp1() {
        return null;
    }

    public void setProp1(String s) {
    }

    public int getProp2() {
        return 0;
    }

    public void setProp2(int i) {
    }

    public byte[] getPROP3() {
        return null;
    }

    public void setPROP3(byte[] bytes) {
    }
}


Exemplo 3 :
BeanInfo: getEventSetDescriptors()

import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
public class Main {
  public static void main(String args[]) {
    try {
      Class c = Class.forName("Colors");
      BeanInfo beanInfo = Introspector.getBeanInfo(c);
      System.out.println("Properties:");
      PropertyDescriptor propertyDescriptor[] = beanInfo.getPropertyDescriptors();
      for (int i = 0; i < propertyDescriptor.length; i++) {
        System.out.println("\t" + propertyDescriptor[i].getName());
      }
      System.out.println("Events:");
      EventSetDescriptor eventSetDescriptor[] = beanInfo.getEventSetDescriptors();
      for (int i = 0; i < eventSetDescriptor.length; i++) {
        System.out.println("\t" + eventSetDescriptor[i].getName());
      }
    } catch (Exception e) {
      System.out.println("Exception caught. " + e);
    }
  }
}

run:
Exception caught. java.lang.ClassNotFoundException: Colors


Exemplo 4:
BeanInfo: getPropertyDescriptors()

package beans2;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
public class Main2 {
  public static void main(String[] argv) throws Exception {
    BeanInfo bi = Introspector.getBeanInfo(MyBean.class);
    PropertyDescriptor[] pds = bi.getPropertyDescriptors();
    for (int i = 0; i < pds.length; i++) {
      String propName = pds[i].getDisplayName();
      System.out.println(propName);
    }
  }
}
class MyBean {
  public String getProp1() {
    return null;
  }
  public void setProp1(String s) {
  }
  public int getProp2() {
    return 0;
  }
  public void setProp2(int i) {
  }
  public byte[] getProp3() {
    return null;
  }
  public void setProp3(byte[] bytes) {
  }
}

run:
PROP3
class
prop1
prop2


Exemplo 5:
EventHandler: create(Class < ActionListener > li, Object t, String a)

package beans2;
import java.awt.event.ActionListener;
import java.beans.EventHandler;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class ContaCliques extends JFrame {

    JLabel label = new JLabel("Leitura...", JLabel.CENTER);
    int count=1;

    public ContaCliques() {
        JButton launchButton = new JButton("Lançar!");
        getContentPane().add(launchButton, "South");
        getContentPane().add(label, "Center");
        launchButton.addActionListener((ActionListener) EventHandler.create(ActionListener.class, this,
                "actionName"));
    }

    public void actionName() {
        label.setText("Lançados: " + count++);
    }

    public static void main(String[] args) {
        JFrame frame = new ContaCliques();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(150, 150);
        frame.setVisible(true);
    }
}

run:


Foram realizados 16 cliques no botão Lançar!


Exemplo 6:
PropertyChangeEvent: getNewValue()

package beans2;

package beans2;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;

public class MudaPropriedade {

    public static void main(String args[]) {
        JFrame frame = new JFrame("Botão Simples");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JButton button1 = new JButton("Mudar cor de ambos botões");
        final JButton button2 = new JButton("Mudar cor só deste botão");
        final Random random = new Random();
        ActionListener actionListener = new ActionListener() {

            public void actionPerformed(ActionEvent actionEvent) {
                JButton button = (JButton) actionEvent.getSource();
                int red = random.nextInt(255);
                int green = random.nextInt(255);
                int blue = random.nextInt(255);
                button.setBackground(new Color(red, green, blue));
            }
        };
        PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
                String property = propertyChangeEvent.getPropertyName();
                if ("background".equals(property)) {
                    button2.setBackground((Color) propertyChangeEvent.getNewValue());
                }
            }
        };
        button1.addActionListener(actionListener);
        button1.addPropertyChangeListener(propertyChangeListener);
        button2.addActionListener(actionListener);
        frame.add(button1, BorderLayout.NORTH);
        frame.add(button2, BorderLayout.SOUTH);
        frame.setSize(300, 100);
        frame.setVisible(true);
    }
}

run:

Ao clicar no primeiro botão, ambos ficaram com uma mesma cor aleatória, clicando no segundo botão, este ficará com uma cor aleatória diferente do primeiro botão.


Exemplo 7:
implements VetoableChangeListener

package beans2;
import java.awt.BorderLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
public class NewClass5 {
  public static void main(final String args[]) {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JDesktopPane desktop = new JDesktopPane();
    JInternalFrame palette = new JInternalFrame("Palette", true, true, true,
        true);
     
    palette.addVetoableChangeListener(new IconPolice());
     
    palette.setBounds(350, 150, 100, 100);
     desktop.add(palette, JDesktopPane.PALETTE_LAYER);
    palette.setVisible(true);
     
    frame.add(desktop, BorderLayout.CENTER);
    frame.setSize(500, 300);
    frame.setVisible(true);
  }
}
class IconPolice implements VetoableChangeListener {
  public void vetoableChange(PropertyChangeEvent ev) throws PropertyVetoException {
    String name = ev.getPropertyName();
    if (name.equals(JInternalFrame.IS_ICON_PROPERTY) && (ev.getNewValue() == Boolean.TRUE)) {
   System.out.println("JInternalFrame.IS_ICON_PROPERTY");
    }
  }
}

run:





Exemplo 8:
Introspector: getBeanInfo(Class beanClass)

package beans2;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

public class Inspetor {

    public static void main(String[] argv) throws Exception {
        BeanInfo bi = Introspector.getBeanInfo(MyBean.class);
        PropertyDescriptor[] pds = bi.getPropertyDescriptors();
        for (int i = 0; i < pds.length; i++) {
            String propName = pds[i].getDisplayName();
            System.out.println(propName);
        }
    }
}

class MyBean5 {

    public String getProp1() {
        return null;
    }

    public void setProp1(String s) {
    }

    public int getProp2() {
        return 0;
    }

    public void setProp2(int i) {
    }

    public byte[] getPROP3() {
        return null;
    }

    public void setPROP3(byte[] bytes) {
    }
}

run:

class
prop1
prop2
prop3


Exemplo 9:
PropertyDescriptor

package beans2;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
public class NewClass6 {
  public static void main(String[] argv) throws Exception {
    BeanInfo bi = Introspector.getBeanInfo(MyBean.class);
    PropertyDescriptor[] pds = bi.getPropertyDescriptors();
    for (int i = 0; i < pds.length; i++) {
      String propName = pds[i].getDisplayName();
      System.out.println(propName);
    }
  }
}
class MyBean6 {
  public String getProp1() {
    return null;
  }
  public void setProp1(String s) {
  }
  public int getProp2() {
    return 0;
  }
  public void setProp2(int i) {
  }
  public byte[] getPROP3() {
    return null;
  }
  public void setPROP3(byte[] bytes) {
  }
}

run:
class
prop1
prop2
prop3