2011-01-16 18 views
7

Un ex colega mío comenzó una discusión hace media hora sobre JavaBeans, y por qué no funcionaron del modo que él quiere en JSF. El caso particular es sobre propiedades booleanas.JavaBeans e introspección: ¿mal estado en propiedades booleanas e indexadas?

. Para una propiedad booleana denominada isUrl Eclipse genera este

private boolean isUrl; 
public boolean isUrl() {..} 
public boolean setUrl(boolean url) {..} 

Pero esto no funciona en JSF. Él hizo el trabajo mediante la adición de public boolean getIsUrl() La aplicación podría ser buggy, así que asegúrese de que tiene razón, mediante el uso de la API de introspección .:

BeanInfo info = Introspector.getBeanInfo(ClassTest.class); 
for (PropertyDescriptor pd : info.getPropertyDescriptors()) { 
     System.out.println(pd.getName() + ": " + pd.getReadMethod() + 
     " : " + pd.getWriteMethod()); 
} 

Para el código anterior, esta opción se imprime ambos métodos - es decir, Eclipse es correcto, JSF Está Mal. Pero eso me sonó sospechoso, ya que the specification no menciona nada sobre el doble "es".

Pero al revisar las especificaciones, vi algo que nunca he usado: las llamadas propiedades indexadas. Puede tener private String[] bar y luego public String getBar(int idx). Entonces:

. Intenté con el Introspector, y no encontré un método de lectura para la barra. El resultado del código anterior fue: bar: null : null. Entonces llegué a pensar: ahora el introspector no sigue las especificaciones. Tal vez no lo siguió en el caso anterior, y en última instancia, JSF tiene razón. De hecho, las propiedades indexadas pueden hacer que haya dos métodos de lectura para una propiedad determinada. Y eso no es posible con la clase PropertyDescriptor de la API de introspección.

¿A qué nos lleva esto? Tenemos una API posiblemente rota que no se ajusta a la especificación. Lo que lleva a otras implementaciones de la especificación (JSF usa una personalizada, obviamente). Lo que lleva a malentendidos y confusiones adicionales.

Una nota al margen de algo que me molestó - en la especificación de JavaBeans llaman a las convenciones de nomenclatura para los métodos de "patrones de diseño". Esto me suena mal.

Así pues, ahora a las preguntas:

  1. es el JavaBeans especificación clara
  2. es la API de introspección correcta
  3. es una especificación de nuevos JavaBeans es necesario, al menos para aclarar el comportamiento de booleanos (que es subjetivo hasta cierto punto)

Actualización. parece que el uso de JSF es bean.isUrl en lugar de bean.url. Lo que hace que tenga sentido no trabajar con el acceso isUrl().

P.S. JDK 1.6.0_20, JSF 1.2, MyFaces

+0

tal vez algo así como las propiedades de C# serán útiles. – Bozho

+0

Después de leer el código de introspector, isXxxx debería funcionar. El nombre del campo utilizado no importa. ¿Has probado Java 6 actualización 23? –

Respuesta

2

Según lo mencionado por @Peter Lawrey, el nombre del campo es irrelevante en lo que respecta a JavaBeans. Ni siquiera necesita existir, o puede darle un nombre tonto como prefijo con m_.

No proporcionó un método de lectura o escritura adecuado para la propiedad bar como un todo, por lo que estos no se mostrarán. No puede sintetizar un Method en una clase existente en tiempo de ejecución.Creo que las propiedades indexadas eran una edición tardía, a pesar de que no existe un @since aparente, por lo que no las utilizan las interfaces java.beans.

No tengo la especificación JSF (y estará detrás del muro del abogado de jcp.org), así que no sé lo que dice. Puede especificar algo diferente a la especificación de JavaBeans [probable], o puede estar utilizando una implementación con errores [supongo que también es probable].

"Patrón de diseño" es solo una frase. Como en un patrón que ocurre en nuestro diseño. No es un patrón de diseño como en GoF.

+0

+1. Sí, la "irrelevancia" del nombre de campo es algo a lo que llegamos en la discusión, y esto explica el comportamiento del eclipse y el introspector. Eclipse es simplemente inteligente. Acerca de los patrones de diseño. Estoy de acuerdo en que es solo una frase, pero que ha recibido un significado muy específico, la que otorga GoF. No es que no signifique nada más, pero es extraño. – Bozho

4

Las propiedades de Java Bean se definen por métodos, no por campos. Por este motivo, la clase PropertyDescriptor tiene los métodos getReadMethod() y getWriteMethod(), pero no los métodos getField().

Personalmente, creo que su colega está utilizando una mala práctica.

a) is es un verbo. Los campos no deben nombrarse después de los verbos.
b) Si bien no es necesario, una buena práctica es nombrar el campo como la propiedad, lo que le permite escribir código como este:

PropertyDescriptor pd; // let's assume this is set 
Method referenceMethod = pd.getReadMethod() == null 
    // at least one of these is not null 
    ? pd.getWriteMethod() : pd.getReadMethod(); 
Field underLyingField = referenceMethod 
          .getDeclaringClass() 
          .getDeclaredField(pd.getName()); 

Mientras que el código no ha sido estandarizada, que está siguiendo las convenciones y puede entrar muy útil. Si no sigue las convenciones de este tipo, no tiene forma de asociar un campo con una propiedad (que es intencional, lo sé).

p. Ej. Yo uso un código como el anterior para comprobar si el campo tiene anotaciones


Sobre propiedades indizadas:

Puede utilizar la sintaxis índice en matriz o propiedades lista (o mapa), pero sólo si están definidos como propiedades estándar de frijol.

Así que si usted tiene una propiedad como esta:

private String[] bar; 
public String[] getBar(){ 
    return bar; 
} 
public void setBar(String[] bar){ 
    this.bar = bar; 
} 

o como esto:

private List<String> bar; 
public List<String> getBar(){ 
    return bar; 
} 
public void setBar(List<String> bar){ 
    this.bar = bar; 
} 

se puede acceder al primer miembro con la expresión ${bar[0]}

Y con un mapa de la propiedad como este:

private Map<String, String> bar; 
public Map<String, String> getBar(){ 
    return bar; 
} 
public void setBar(Map<String, String> bar){ 
    this.bar = bar; 
} 

Puede acceder al valor asignado a "baz" como este ${bar['baz']}.

Esta funcionalidad se basa en la funcionalidad de beans estándar, por lo que requiere getters/setters regulares.

+0

(+1).en general, estoy de acuerdo en que una propiedad booleana no debe incluir 'is', pero para mí tiene sentido si el nombre del campo es un nombre, en lugar de un adjetivo. – Bozho

+1

@Bozho gracioso, pensé que era una convención muy aceptada que los nombres de campo no deberían ser verbos, pero no puedo encontrar nada para respaldar esa afirmación. Todo el mundo dice que un nombre de método debería ser un verbo, y para mí eso implica que un campo no debería, pero nadie lo dice explícitamente (ni de Sun, Wikipedia, Joshua Bloch). –

Cuestiones relacionadas