java:javabeans
Differences
This shows you the differences between two versions of the page.
Previous revision | |||
— | java:javabeans [2022/12/02 22:02] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Java Beans ====== | ||
+ | |||
+ | ===== Introducción ===== | ||
+ | |||
+ | Los Java Beans -en castellano granos de café java- no son otra cosa que un modelo de componentes para Java. Se estandariza la forma de definir las propiedades (métodos get y set), cómo deben notificarse cambios en los estados del componente (propiedades ligadas, constraints) y cómo acceder a colecciones de elementos (propiedades índice). | ||
+ | |||
+ | Estas notas están sacadas del [[http:// | ||
+ | |||
+ | ===== Propiedades sencilla ===== | ||
+ | |||
+ | Un java bean sencillo: | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | public class MyBean { | ||
+ | | ||
+ | /** Creates a new instance of MyBean */ | ||
+ | public MyBean() { | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Holds value of property yourName. | ||
+ | */ | ||
+ | private String yourName; | ||
+ | |||
+ | /** | ||
+ | * Getter for property yourName. | ||
+ | * @return Value of property yourName. | ||
+ | */ | ||
+ | public String getYourName() { | ||
+ | return this.yourName; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Setter for property yourName. | ||
+ | * @param yourName New value of property yourName. | ||
+ | */ | ||
+ | public void setYourName(String yourName) { | ||
+ | this.yourName = yourName; | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | Las propiedades exponen dos métodos públicos: getNombrePropiedad y setNombrePropiedad. El " | ||
+ | |||
+ | ===== Propiedades Indexadas ===== | ||
+ | |||
+ | Cuando una propiedad debe exponer una colección de elementos (el acceso a una lista de valores), los métodos a programar son cuatro: | ||
+ | |||
+ | * String getNombrePropiedad( int index ) - devolverá el elemento de la enésima posición de la lista | ||
+ | * String[] getNombrePropiedad() - devolverá una copia de la colección completa | ||
+ | * void setNombrePropiedad( int index, String valor ) - establece el enésimo elemento de la lista | ||
+ | * void setNombrePropiedad( String[] valores ) - establece la colección completa | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | /** | ||
+ | * Holds value of property lines. | ||
+ | */ | ||
+ | private String[] lines; | ||
+ | |||
+ | /** | ||
+ | * Indexed getter for property lines. | ||
+ | * @param index Index of the property. | ||
+ | * @return Value of the property at index. | ||
+ | */ | ||
+ | public String getLines(int index) { | ||
+ | return this.lines[index]; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Getter for property lines. | ||
+ | * @return Value of property lines. | ||
+ | */ | ||
+ | public String[] getLines() { | ||
+ | return this.lines; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Indexed setter for property lines. | ||
+ | * @param index Index of the property. | ||
+ | * @param lines New value of the property at index. | ||
+ | */ | ||
+ | public void setLines(int index, String lines) { | ||
+ | this.lines[index] = lines; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Setter for property lines. | ||
+ | * @param lines New value of property lines. | ||
+ | */ | ||
+ | public void setLines(String[] lines) { | ||
+ | this.lines = lines; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== Propiedades Ligadas ===== | ||
+ | |||
+ | Lo que haremos en este caso es utilizar un objeto [[http:// | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | import java.awt.Graphics; | ||
+ | import java.beans.PropertyChangeListener; | ||
+ | import java.beans.PropertyChangeSupport; | ||
+ | import java.io.Serializable; | ||
+ | import javax.swing.JComponent; | ||
+ | |||
+ | /** | ||
+ | * Bean with bound properties. | ||
+ | */ | ||
+ | public class MyBean | ||
+ | extends JComponent | ||
+ | implements Serializable | ||
+ | { | ||
+ | private String title; | ||
+ | private String[] lines = new String[10]; | ||
+ | |||
+ | private final PropertyChangeSupport pcs = new PropertyChangeSupport( this ); | ||
+ | |||
+ | public String getTitle() | ||
+ | { | ||
+ | return this.title; | ||
+ | } | ||
+ | |||
+ | public void setTitle( String title ) | ||
+ | { | ||
+ | String old = this.title; | ||
+ | this.title = title; | ||
+ | this.pcs.firePropertyChange( " | ||
+ | } | ||
+ | |||
+ | public String[] getLines() | ||
+ | { | ||
+ | return this.lines.clone(); | ||
+ | } | ||
+ | |||
+ | public String getLines( int index ) | ||
+ | { | ||
+ | return this.lines[index]; | ||
+ | } | ||
+ | |||
+ | public void setLines( String[] lines ) | ||
+ | { | ||
+ | String[] old = this.lines; | ||
+ | this.lines = lines; | ||
+ | this.pcs.firePropertyChange( " | ||
+ | } | ||
+ | |||
+ | public void setLines( int index, String line ) | ||
+ | { | ||
+ | String old = this.lines[index]; | ||
+ | this.lines[index] = line; | ||
+ | this.pcs.fireIndexedPropertyChange( " | ||
+ | } | ||
+ | |||
+ | public void addPropertyChangeListener( PropertyChangeListener listener ) | ||
+ | { | ||
+ | this.pcs.addPropertyChangeListener( listener ); | ||
+ | } | ||
+ | |||
+ | public void removePropertyChangeListener( PropertyChangeListener listener ) | ||
+ | { | ||
+ | this.pcs.removePropertyChangeListener( listener ); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Propiedades ligadas y limitadas ===== | ||
+ | |||
+ | Existe también la posibilidad de que los listeners puedan " | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | import java.io.Serializable; | ||
+ | import java.beans.PropertyChangeListener; | ||
+ | import java.beans.PropertyChangeSupport; | ||
+ | import java.beans.PropertyVetoException; | ||
+ | import java.beans.VetoableChangeListener; | ||
+ | import java.beans.VetoableChangeSupport; | ||
+ | import java.awt.Graphics; | ||
+ | import javax.swing.JComponent; | ||
+ | |||
+ | /** | ||
+ | * Bean with constrained properties. | ||
+ | */ | ||
+ | public class MyBean | ||
+ | extends JComponent | ||
+ | implements Serializable | ||
+ | { | ||
+ | private String title; | ||
+ | private String[] lines = new String[10]; | ||
+ | |||
+ | private final PropertyChangeSupport pcs = new PropertyChangeSupport( this ); | ||
+ | private final VetoableChangeSupport vcs = new VetoableChangeSupport( this ); | ||
+ | |||
+ | public String getTitle() | ||
+ | { | ||
+ | return this.title; | ||
+ | } | ||
+ | /** | ||
+ | * This method was modified to throw the PropertyVetoException | ||
+ | * if some vetoable listeners reject the new title value | ||
+ | */ | ||
+ | public void setTitle( String title ) | ||
+ | throws PropertyVetoException | ||
+ | { | ||
+ | String old = this.title; | ||
+ | this.vcs.fireVetoableChange( " | ||
+ | this.title = title; | ||
+ | this.pcs.firePropertyChange( " | ||
+ | } | ||
+ | |||
+ | public String[] getLines() | ||
+ | { | ||
+ | return this.lines.clone(); | ||
+ | } | ||
+ | |||
+ | public String getLines( int index ) | ||
+ | { | ||
+ | return this.lines[index]; | ||
+ | } | ||
+ | /** | ||
+ | * This method throws the PropertyVetoException | ||
+ | * if some vetoable listeners reject the new lines value | ||
+ | */ | ||
+ | public void setLines( String[] lines ) | ||
+ | throws PropertyVetoException | ||
+ | { | ||
+ | String[] old = this.lines; | ||
+ | this.vcs.fireVetoableChange( " | ||
+ | this.lines = lines; | ||
+ | this.pcs.firePropertyChange( " | ||
+ | } | ||
+ | |||
+ | public void setLines( int index, String line ) | ||
+ | throws PropertyVetoException | ||
+ | { | ||
+ | String old = this.lines[index]; | ||
+ | this.vcs.fireVetoableChange( " | ||
+ | this.lines[index] = line; | ||
+ | this.pcs.fireIndexedPropertyChange( " | ||
+ | } | ||
+ | |||
+ | public void addPropertyChangeListener( PropertyChangeListener listener ) | ||
+ | { | ||
+ | this.pcs.addPropertyChangeListener( listener ); | ||
+ | } | ||
+ | |||
+ | public void removePropertyChangeListener( PropertyChangeListener listener ) | ||
+ | { | ||
+ | this.pcs.removePropertyChangeListener( listener ); | ||
+ | } | ||
+ | /** | ||
+ | * Registration of the VetoableChangeListener | ||
+ | */ | ||
+ | public void addVetoableChangeListener( VetoableChangeListener listener ) | ||
+ | { | ||
+ | this.vcs.addVetoableChangeListener( listener ); | ||
+ | } | ||
+ | |||
+ | public void removeVetoableChangeListener( VetoableChangeListener listener ) | ||
+ | { | ||
+ | this.vcs.removeVetoableChangeListener( listener ); | ||
+ | } | ||
+ | |||
+ | protected void paintComponent( Graphics g ) | ||
+ | { | ||
+ | g.setColor( getForeground() ); | ||
+ | |||
+ | int height = g.getFontMetrics().getHeight(); | ||
+ | paintString( g, this.title, height ); | ||
+ | |||
+ | if ( this.lines != null ) | ||
+ | { | ||
+ | int step = height; | ||
+ | for ( String line : this.lines ) | ||
+ | paintString( g, line, height += step ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | private void paintString( Graphics g, String str, int height ) | ||
+ | { | ||
+ | if ( str != null ) | ||
+ | g.drawString( str, 0, height ); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ===== Persistencia: | ||
+ | |||
+ | Hay dos modos de que un java bean pueda alcanzar la persistencia: | ||
+ | |||
+ | La **serialización** se consigue implentando el interfaz Serializable, | ||
+ | |||
+ | Si la clase padre ya implementa Serializable, | ||
+ | |||
+ | Si queremos que una clase o método no se guarde en el proceso de serialización, | ||
+ | |||
+ | Podemos hacer que la serialización no funcione por defecto implementando estos dos métodos en nuestra clase: | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | private void writeObject( java.io.ObjectOutputStream out) throws IOException; | ||
+ | |||
+ | private void readObject( java.io.ObjectInputStream out) throws IOException, | ||
+ | |||
+ | </ | ||
+ | |||
+ | La **externalización** exige de un mayor trabajo por nuestra parte, y está pensada para que el contenido del java bean se escriba en disco. | ||
+ | |||
+ | Se hace básicamente heredando el interfaz Externalizable e implementando a continuación los métodos readExternal y writeExternal. | ||
+ | |||
+ | La clase que implemente Externalizable tiene que tener un constructor sin argumentos. | ||
+ | |||
+ | ===== Codificando y descodificando un objeto en XML ===== | ||
+ | |||
+ | La clase [[http:// | ||
+ | |||
+ | <code java> | ||
+ | XMLEncoder e = new XMLEncoder( | ||
+ | new BufferedOutputStream( | ||
+ | new FileOutputStream(" | ||
+ | e.writeObject(object); | ||
+ | e.close() | ||
+ | </ | ||
+ | |||
+ | <code java> | ||
+ | XMLDecoder decoder = new XMLDecoder( | ||
+ | new BufferedInputStream( | ||
+ | new FileInputStream( " | ||
+ | Object object = decoder.readObject(); | ||
+ | decoder.close(); | ||
+ | </ | ||
+ | |||