关于IndexedPropertyDescriptor,JRE 1.8是否仍然符合JavaBean规范?

关于IndexedPropertyDescriptor,JRE 1.8是否仍然符合JavaBean规范?,java,javabeans,introspection,Java,Javabeans,Introspection,这个问题看起来很尴尬,但我们在检索javabean的PropertyDescriptor时遇到了一个奇怪的行为。 下面是一段简单代码在1.6、1.7和1.8上的执行结果,该代码是按照1.6标准编译的 Java 1.6执行: java.bean。PropertyDescriptor@4ddc1428来自JavaBeans 1.01规范第7.2节“索引属性”: 组件还可以将索引属性作为单个数组值公开 第8.3节描述了在没有明确BeanInfo的情况下识别的设计模式。第8.3.3节指出,只有数组属性才

这个问题看起来很尴尬,但我们在检索javabean的PropertyDescriptor时遇到了一个奇怪的行为。 下面是一段简单代码在1.6、1.7和1.8上的执行结果,该代码是按照1.6标准编译的

Java 1.6执行:


java.bean。PropertyDescriptor@4ddc1428来自JavaBeans 1.01规范第7.2节“索引属性”:

组件还可以将索引属性作为单个数组值公开

第8.3节描述了在没有明确BeanInfo的情况下识别的设计模式。第8.3.3节指出,只有数组属性才会触发索引属性的自动识别

你在技术上是正确的;不强制使用数组。但是如果您不这样做,规范说您必须提供您自己的BeanInfo以将属性作为索引属性公开

因此,您的问题标题的答案是:是的,Java1.8符合JavaBean规范

我不知道为什么列表属性曾经被支持。也许未来的JavaBeans规范将支持它们,但该规范已被撤销

至于最后一个问题:我认为您必须为每个具有列表属性的类创建一个BeanInfo类。我希望您可以创建一个通用的超类来简化它,例如:

public abstract class ListRecognizingBeanInfo
extends SimpleBeanInfo {

    private final BeanDescriptor beanDesc;
    private final PropertyDescriptor[] propDesc;

    protected ListRecognizingBeanInfo(Class<?> beanClass)
    throws IntrospectionException {
        beanDesc = new BeanDescriptor(beanClass);

        List<PropertyDescriptor> desc = new ArrayList<>();

        for (Method method : beanClass.getMethods()) {
            int modifiers = method.getModifiers();
            Class<?> type = method.getReturnType();

            if (Modifier.isPublic(modifiers) &&
                !Modifier.isStatic(modifiers) &&
                !type.equals(Void.TYPE) &&
                method.getParameterCount() == 0) {

                String name = method.getName();
                String remainder;
                if (name.startsWith("get")) {
                    remainder = name.substring(3);
                } else if (name.startsWith("is") &&
                           type.equals(Boolean.TYPE)) {
                    remainder = name.substring(2);
                } else {
                    continue;
                }

                if (remainder.isEmpty()) {
                    continue;
                }

                String propName = Introspector.decapitalize(remainder);

                Method writeMethod = null;
                Method possibleWriteMethod =
                    findMethod(beanClass, "set" + remainder, type);
                if (possibleWriteMethod != null &&
                    possibleWriteMethod.getReturnType().equals(Void.TYPE)) {

                    writeMethod = possibleWriteMethod;
                }

                Class<?> componentType = null;
                if (type.isArray()) {
                    componentType = type.getComponentType();
                } else {
                    Type genType = method.getGenericReturnType();
                    if (genType instanceof ParameterizedType) {
                        ParameterizedType p = (ParameterizedType) genType;
                        if (p.getRawType().equals(List.class)) {
                            Type[] argTypes = p.getActualTypeArguments();
                            if (argTypes[0] instanceof Class) {
                                componentType = (Class<?>) argTypes[0];
                            }
                        }
                    }
                }

                Method indexedReadMethod = null;
                Method indexedWriteMethod = null;

                if (componentType != null) {
                    Method possibleReadMethod =
                        findMethod(beanClass, name, Integer.TYPE);
                    Class<?> idxType = possibleReadMethod.getReturnType();
                    if (idxType.equals(componentType)) {
                        indexedReadMethod = possibleReadMethod;
                    }

                    if (writeMethod != null) {
                        possibleWriteMethod =
                            findMethod(beanClass, writeMethod.getName(),
                                Integer.TYPE, componentType);
                        if (possibleWriteMethod != null &&
                            possibleWriteMethod.getReturnType().equals(
                                Void.TYPE)) {

                            indexedWriteMethod = possibleWriteMethod;
                        }
                    }
                }

                if (indexedReadMethod != null) {
                    desc.add(new IndexedPropertyDescriptor(propName,
                        method, writeMethod,
                        indexedReadMethod, indexedWriteMethod));
                } else {
                    desc.add(new PropertyDescriptor(propName,
                        method, writeMethod));
                }
            }
        }

        propDesc = desc.toArray(new PropertyDescriptor[0]);
    }

    private static Method findMethod(Class<?> cls,
                                     String name,
                                     Class<?>... paramTypes) {
        try {
            Method method = cls.getMethod(name, paramTypes);
            int modifiers = method.getModifiers();
            if (Modifier.isPublic(modifiers) &&
                !Modifier.isStatic(modifiers)) {

                return method;
            }
        } catch (NoSuchMethodException e) {
        }

        return null;
    }

    @Override
    public BeanDescriptor getBeanDescriptor() {
        return beanDesc;
    }

    @Override
    public PropertyDescriptor[] getPropertyDescriptors() {
        return propDesc;
    }
}
公共抽象类ListRecognizingBeanInfo
扩展SimpleBeanifo{
私人最终BeanDescriptor beanDesc;
私有最终属性描述器[]propDesc;
受保护的ListRecognizingBeanInfo(类beanClass)
抛出内省异常{
beanDesc=新的BeanDescriptor(beanClass);
List desc=new ArrayList();
for(方法:beanClass.getMethods()){
int modifiers=method.getModifiers();
Class type=method.getReturnType();
if(修饰符.isPublic)(修饰符)&&
!Modifier.isStatic(修饰符)&&
!type.equals(Void.type)&&
方法。getParameterCount()=0){
String name=method.getName();
字符串余数;
if(name.startsWith(“get”)){
余数=名称。子字符串(3);
}else if(name.startsWith(“is”)&&
type.equals(Boolean.type)){
余数=名称。子字符串(2);
}否则{
继续;
}
if(余数.isEmpty()){
继续;
}
String propName=Introspector.decapitalize(余数);
方法writeMethod=null;
方法可能写方法=
findMethod(beanClass,“set”+余数,类型);
if(可能的WriteMethod!=null&&
可能的WriteMethod.getReturnType().equals(Void.TYPE)){
writeMethod=可能的writeMethod;
}
类componentType=null;
if(type.isArray()){
componentType=type.getComponentType();
}否则{
类型genType=method.getGenericReturnType();
if(参数化类型的genType实例){
ParameteredType p=(ParameteredType)genType;
if(p.getRawType().equals(List.class)){
类型[]argTypes=p.getActualTypeArguments();
if(argTypes[0]instanceof类){
componentType=(类)argTypes[0];
}
}
}
}
方法IndexeDeardMethod=null;
方法indexedWriteMethod=null;
if(componentType!=null){
方法可能的方法=
findMethod(beanClass、name、Integer.TYPE);
类idxType=possibleReadMethod.getReturnType();
if(idxType.equals(componentType)){
indexedReadMethod=可能的方法;
}
if(writeMethod!=null){
可能的写方法=
findMethod(beanClass,writeMethod.getName(),
Integer.TYPE,componentType);
if(可能的WriteMethod!=null&&
可能的WriteMethod.getReturnType().equals(
无效(类型){
indexedWriteMethod=可能的WriteMethod;
}
}
}
if(indexederDaredMethod!=null){
desc.add(新的IndexedPropertyDescriptor(propName,
方法,writeMethod,
indexedWriteMethod,indexedWriteMethod);
}否则{
desc.add(新属性)描述器(propName,
方法(writeMethod);
}
}
}
propDesc=desc.toArray(新的PropertyDescriptor[0]);
}
私有静态方法findMethod(类cls,
字符串名,
类…参数类型){
试一试{
Method=cls.getMethod(名称、参数类型);
int modifiers=method.getModifiers();
if(修饰符.isPublic)(修饰符)&&
!修饰符.isStatic(修饰符)){
返回法;
}
}捕获(无此方法例外){
}
返回null;
}
@凌驾
公共BeanDescriptor getBeanDescriptor(){
返回beanDesc;
}
@凌驾
公共PropertyDescriptor[]getPropertyDescriptors(){
返回propDesc;
}
}

我也面临同样的问题。
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;

public class Test {
    public static void main(String[] args) throws IntrospectionException {
         PropertyDescriptor[] descs =
         Introspector.getBeanInfo(JavaBean.class).getPropertyDescriptors();
         for (PropertyDescriptor pd : descs) {
         System.out.println(pd);
         }
    }
}
public abstract class ListRecognizingBeanInfo
extends SimpleBeanInfo {

    private final BeanDescriptor beanDesc;
    private final PropertyDescriptor[] propDesc;

    protected ListRecognizingBeanInfo(Class<?> beanClass)
    throws IntrospectionException {
        beanDesc = new BeanDescriptor(beanClass);

        List<PropertyDescriptor> desc = new ArrayList<>();

        for (Method method : beanClass.getMethods()) {
            int modifiers = method.getModifiers();
            Class<?> type = method.getReturnType();

            if (Modifier.isPublic(modifiers) &&
                !Modifier.isStatic(modifiers) &&
                !type.equals(Void.TYPE) &&
                method.getParameterCount() == 0) {

                String name = method.getName();
                String remainder;
                if (name.startsWith("get")) {
                    remainder = name.substring(3);
                } else if (name.startsWith("is") &&
                           type.equals(Boolean.TYPE)) {
                    remainder = name.substring(2);
                } else {
                    continue;
                }

                if (remainder.isEmpty()) {
                    continue;
                }

                String propName = Introspector.decapitalize(remainder);

                Method writeMethod = null;
                Method possibleWriteMethod =
                    findMethod(beanClass, "set" + remainder, type);
                if (possibleWriteMethod != null &&
                    possibleWriteMethod.getReturnType().equals(Void.TYPE)) {

                    writeMethod = possibleWriteMethod;
                }

                Class<?> componentType = null;
                if (type.isArray()) {
                    componentType = type.getComponentType();
                } else {
                    Type genType = method.getGenericReturnType();
                    if (genType instanceof ParameterizedType) {
                        ParameterizedType p = (ParameterizedType) genType;
                        if (p.getRawType().equals(List.class)) {
                            Type[] argTypes = p.getActualTypeArguments();
                            if (argTypes[0] instanceof Class) {
                                componentType = (Class<?>) argTypes[0];
                            }
                        }
                    }
                }

                Method indexedReadMethod = null;
                Method indexedWriteMethod = null;

                if (componentType != null) {
                    Method possibleReadMethod =
                        findMethod(beanClass, name, Integer.TYPE);
                    Class<?> idxType = possibleReadMethod.getReturnType();
                    if (idxType.equals(componentType)) {
                        indexedReadMethod = possibleReadMethod;
                    }

                    if (writeMethod != null) {
                        possibleWriteMethod =
                            findMethod(beanClass, writeMethod.getName(),
                                Integer.TYPE, componentType);
                        if (possibleWriteMethod != null &&
                            possibleWriteMethod.getReturnType().equals(
                                Void.TYPE)) {

                            indexedWriteMethod = possibleWriteMethod;
                        }
                    }
                }

                if (indexedReadMethod != null) {
                    desc.add(new IndexedPropertyDescriptor(propName,
                        method, writeMethod,
                        indexedReadMethod, indexedWriteMethod));
                } else {
                    desc.add(new PropertyDescriptor(propName,
                        method, writeMethod));
                }
            }
        }

        propDesc = desc.toArray(new PropertyDescriptor[0]);
    }

    private static Method findMethod(Class<?> cls,
                                     String name,
                                     Class<?>... paramTypes) {
        try {
            Method method = cls.getMethod(name, paramTypes);
            int modifiers = method.getModifiers();
            if (Modifier.isPublic(modifiers) &&
                !Modifier.isStatic(modifiers)) {

                return method;
            }
        } catch (NoSuchMethodException e) {
        }

        return null;
    }

    @Override
    public BeanDescriptor getBeanDescriptor() {
        return beanDesc;
    }

    @Override
    public PropertyDescriptor[] getPropertyDescriptors() {
        return propDesc;
    }
}
<cc:dateInput property='<%= "startDateStrings[" + row + "]" %>' onchange="setPropertyChangedFlag()"/>                     
<cc:dateInput property='<%= "endDateStrings[" + row + "]" %>' onchange="setPropertyChangedFlag()"/>                     
public List<String> getStartDateStrings() {
  return startDateStrings;
}
public String getStartDateStrings(int index) {
    return startDateStrings.get(index);
  }
public void setStartDateStrings(int index, String value) {
    startDateStrings.set(index, value);
  }
public List<String> getEndDateStrings() {
    return endDateStrings;
  }
public String getEndDateStrings(int index) {
    return endDateStrings.get(index);
  }
public void setEndDateStrings(int index, String value) {
    endDateStrings.set(index, value);