自JDK 7以来,Java JDK 8 IndexedPropertyDescriptor已使用List对象进行了更改

我有一个简单的问题。 我有一个在Java JDK7中工作的程序,但由于一些内省的更改,它在JDK8中不起作用。

这是一个重现问题的测试程序:

import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) throws IntrospectionException { BeanInfo info = Introspector.getBeanInfo(MyListClass.class); PropertyDescriptor[] descriptors = info.getPropertyDescriptors(); for (int i = 0; i < descriptors.length; i++) { System.out.println(descriptors[i].getClass().getName() + ":" + descriptors[i].getName()); } System.out.println("\n"); BeanInfo info2 = Introspector.getBeanInfo(MyIndexedListClass.class); PropertyDescriptor[] descriptors2 = info2.getPropertyDescriptors(); for (int i = 0; i < descriptors2.length; i++) { System.out.println(descriptors2[i].getClass().getName() + ":" + descriptors2[i].getName()); } System.out.println("\n"); BeanInfo info3 = Introspector.getBeanInfo(MyArrayClass.class); PropertyDescriptor[] descriptors3 = info3.getPropertyDescriptors(); for (int i = 0; i < descriptors3.length; i++) { System.out.println(descriptors3[i].getClass().getName() + ":" + descriptors3[i].getName()); } System.out.println("\n"); BeanInfo info4 = Introspector.getBeanInfo(MyIndexedArrayClass.class); PropertyDescriptor[] descriptors4 = info4.getPropertyDescriptors(); for (int i = 0; i < descriptors4.length; i++) { System.out.println(descriptors4[i].getClass().getName() + ":" + descriptors4[i].getName()); } } public class MyListClass { private List myListClass = new ArrayList(); public List getMyListClass() { return myListClass; } public void setMyListClass(List myListClass) { this.myListClass = myListClass; } } public class MyIndexedListClass { private List myIndexedListClass = new ArrayList(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List getMyIndexedListClass() { return myIndexedListClass; } public void setMyIndexedListClass(List myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } public class MyArrayClass { private String[] myArrayClass = new String[20]; public String[] getMyArrayClass() { return myArrayClass; } public void setMyArrayClass(String[] myArrayClass) { this.myArrayClass = myArrayClass; } } public class MyIndexedArrayClass { private String[] myIndexedArrayClass = new String[20]; public String getMyIndexedArrayClass(int index) { return myIndexedArrayClass[index]; } public void setMyIndexedArrayClass(int index, String myValue) { this.myIndexedArrayClass[index] = myValue; } public String[] getMyIndexedArrayClass() { return myIndexedArrayClass; } public void setMyIndexedArrayClass(String[] myIndexedArrayClass) { this.myIndexedArrayClass = myIndexedArrayClass; } } } 

以下是JDK 7日志:

 java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myListClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedListClass java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myArrayClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedArrayClass 

以下是JDK8的日志:

 java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myListClass java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myIndexedListClass -> Here is the change java.beans.PropertyDescriptor:class java.beans.PropertyDescriptor:myArrayClass java.beans.PropertyDescriptor:class java.beans.IndexedPropertyDescriptor:myIndexedArrayClass 

我必须尽快使用JDK8,但这是一个阻止更改,因为我的应用程序不再起作用了。 我对扩展Collection接口的所有类(List,Map,…)都有这个问题

该代码由Apache Commons的库commons-beanutils-1.8.0使用。

我正在寻找一种解决方案,一种解决方法,使我的应用程序像以前一样工作,使用JDK7时,有什么解决方案吗? 我不能使用Array而不是List(因为Array没有改变)

以下是官方文档的链接:

JDK7: http : //docs.oracle.com/javase/7/docs/api/java/beans/IndexedPropertyDescriptor.html

JDK8: http ://docs.oracle.com/javase/8/docs/api/java/beans/IndexedPropertyDescriptor.html


编辑:我找到了我的解决方案,我的问题与struts 1.3有关。 我必须在ActionForm中重命名索引的getter / setter: http : //www.coderanch.com/t/55172/Struts/Indexed-Properties

好吧,规范明确指出IndexedPropertyDescriptor可能有其他基于数组的访问器方法,没有别的。 这没有改变。 你在这里有一个冲突的属性方法定义一个简单的List类型属性和一个同名的索引String属性。 基于List的方法从未与索引属性相关联。

所以改变了哪些冲突的属性使它成为BeanInfo并将被删除。 此行为可能取决于HashMap的未指定顺序或类似情况。 可能还有其他因素。 因此,不要将其视为Java 7与Java 8问题,而只是一种依赖于实现的行为,这种行为也可能在备用Java 7实现之间发生变化。

有两种方法可以解决此问题。 您可以通过重命名其中一个属性来解决冲突:

 public class MyIndexedListClass { private List myIndexedListClass = new ArrayList(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List getMyIndexedListClassAsList() { return myIndexedListClass; } public void setMyIndexedListClassAsList(List myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } 

然后,所有Java版本的行为都相同,但它具有现在将两个不同属性视为不同命名属性的副作用。


另一种方法是保持方法不变,但明确地从属性描述符识别中删除基于List的方法。 换句话说,使行为发生在一个实现中并且似乎是您期望的行为。

 public class MyIndexedListClass { private List myIndexedListClass = new ArrayList(); public String getMyIndexedListClass(int index) { return myIndexedListClass.get(index); } public void setMyIndexedListClass(int index, String element) { this.myIndexedListClass.set(index, element); } public List getMyIndexedListClass() { return myIndexedListClass; } public void setMyIndexedListClass(List myIndexedListClass) { this.myIndexedListClass = myIndexedListClass; } } static // in your example all classes are inner classes public class MyIndexedListClassBeanInfo extends SimpleBeanInfo { private PropertyDescriptor[] properties; public MyIndexedListClassBeanInfo() throws IntrospectionException { PropertyDescriptor[] p=Introspector.getBeanInfo(MyIndexedListClass.class, Introspector.IGNORE_IMMEDIATE_BEANINFO).getPropertyDescriptors(); ArrayList list=new ArrayList<>(p.length+1); for(PropertyDescriptor d: p) if(!d.getName().equals("myIndexedListClass")) list.add(d); list.add(new IndexedPropertyDescriptor("myIndexedListClass", MyIndexedListClass.class, null, null, "getMyIndexedListClass", "setMyIndexedListClass")); properties=list.toArray(new PropertyDescriptor[list.size()]); } @Override public PropertyDescriptor[] getPropertyDescriptors() { return properties; } } 
Interesting Posts