Is JRE 1.8 still JavaBean specifications compatible with IndexedPropertyDescriptor?

This question seems uncomfortable, but we come across strange behavior when retrieving javabean PropertyDescriptors. Here are the results of running 1.6, 1.7, and 1.8 of the simple part of the code compiled in compliance with 1.6.

Running Java 1.6:

java.beans.PropertyDescriptor@4ddc1428 <- Doesn’t matter java.beans.IndexedPropertyDescriptor@7174807e <- Yes I have an indexed property

Running Java 1.7:

java.beans.PropertyDescriptor [name = class; propertyType = class java.lang.Class; readMethod = public final native java.lang.Class java.lang.Object.getClass ()] <- It does not matter java.beans.IndexedPropertyDescriptor [name = values; indexedPropertyType = class java.lang.String; indexedReadMethod = public java.lang.String JavaBean.getValues ​​(int)] <- Yes I have an indexed property

Running Java 1.8:

java.beans.PropertyDescriptor [name = class; propertyType = class java.lang.Class; readMethod = public final native java.lang.Class java.lang.Object.getClass ()] <- It does not matter java.beans.PropertyDescriptor [name = values; propertyType = interface java.util.List; readMethod = public java.util.List JavaBean.getValues ​​()] <- Ouch! This is no longer an indexed property!

Why has he changed?

javabean specs . . ?

, 8.3.3 , .

? < , ..

,

JavaBean

import java.util.ArrayList;  
import java.util.List;  


public class JavaBean {  


  private List<String> values = new ArrayList<String>();  


  public String getValues(int index) {  
  return this.values.get(index);  
  }  


  public List<String> getValues() {  
  return this.values;  
  }  
}  

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);
         }
    }
}
+4
1

JavaBeans 1.01, 7.2 " ":

.

8.3 , introspection BeanInfo. 8.3.3 , .

; . , , BeanInfo, .

, : , Java 1.8 JavaBean.

, List - . , JavaBeans , .

: , BeanInfo List. , , , :

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;
    }
}
+2

Source: https://habr.com/ru/post/1623794/