本文介绍了自JDK 7以来,Java JDK 8 IndexedPropertyDescriptor已使用List对象进行了更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a simple issue. I have a program working in Java JDK7 but it doesn't work in JDK8 because of some introspection changes.

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

Here is a test program to reproduce the issue:

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<String> myListClass = new ArrayList<String>();

        public List<String> getMyListClass() {
            return myListClass;
        }

        public void setMyListClass(List<String> myListClass) {
            this.myListClass = myListClass;
        }

    }

    public class MyIndexedListClass {
        private List<String> myIndexedListClass = new ArrayList<String>();

        public String getMyIndexedListClass(int index) {
            return myIndexedListClass.get(index);
        }

        public void setMyIndexedListClass(int index, String element) {
            this.myIndexedListClass.set(index, element);
        }

        public List<String> getMyIndexedListClass() {
            return myIndexedListClass;
        }

        public void setMyIndexedListClass(List<String> 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日志:

Here are the JDK 7 logs:

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的日志:

Here are the logs for 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,但这是一个阻塞更改,因为我的应用程序不再起作用了。我对所有扩展集合接口的类(List,Map,...)有这个问题

I have to use the JDK8 really soon but this is a blocking change because my app doesn't work anymore. I have this issue with all the classes that extend the Collection interface (List, Map, ...)

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

The code is used by the library commons-beanutils-1.8.0 from Apache Commons.

我正在寻找对于解决方案,一种解决方法,使我的应用程序以与以前相同的方式运行,在使用JDK7时,有什么解决方案吗?我不能使用Array而不是List(因为Array没有改变)

I'm looking for a solution, a workaround, to make my application work the same way as before, when using the JDK7, is there any solution? I can't use Array instead of List (because Array hasn't changed)

以下是官方文档的链接:

Here are the links to the official documentation:

JDK7:

JDK8:

编辑:我找到了我的解决方案,我的问题与struts 1.3有关。我必须在我的ActionForm中重命名索引的getter / setter:

EDIT : I found my solution, my problem was related with struts 1.3. I had to rename my indexed getter/setter in my ActionForm :http://www.coderanch.com/t/55172/Struts/Indexed-Properties

推荐答案

嗯,规范清楚地说, IndexedPropertyDescriptor 可能有其他基于数组的访问器方法,没有别的。这没有改变。你在这里有冲突的属性方法定义一个简单的列表< String> 类型的属性和一个索引的字符串同名的财产。基于 List 的方法从未与索引属性相关联。

Well, the specification clearly says that an IndexedPropertyDescriptor may have additional array based accessor methods, nothing else. That hasn’t changed. What you have here are conflicting property methods defining a simple List<String> typed property and and an indexed String property of the same name. The List based methods were never associated with the indexed property.

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

So what has changed is which of the conflicting properties makes it into the BeanInfo and which will be dropped. This behavior might be dependent on the unspecified order of a HashMap or such alike. There might be other factors as well. Thus, don’t see it as a Java 7 vs. Java 8 issue, but just an implementation dependent behavior which may also change between alternative Java 7 implementations.

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

There are two ways to resolve this problem. You may solve the conflict by renaming one of the properties:

public class MyIndexedListClass {
    private List<String> myIndexedListClass = new ArrayList<String>();

    public String getMyIndexedListClass(int index) {
        return myIndexedListClass.get(index);
    }

    public void setMyIndexedListClass(int index, String element) {
        this.myIndexedListClass.set(index, element);
    }

    public List<String> getMyIndexedListClassAsList() {
        return myIndexedListClass;
    }

    public void setMyIndexedListClassAsList(List<String> myIndexedListClass) {
        this.myIndexedListClass = myIndexedListClass;
    }
}

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

Then, all Java versions will behave the same, but it has the side effect of now seeing the two different properties as differently named properties.

另一种方法是保留方法原样但明确地从属性描述符识别中删除基于 List 的方法。换句话说,使行为发生在一个实现中并且似乎是您想要的行为,显式。

The alternative is to keep the methods as is but explicitly elide the List based methods from the property descriptor recognition. In other words, make the behavior, which happened in one implementation and seems to be your desired one, explicit.

public class MyIndexedListClass {
    private List<String> myIndexedListClass = new ArrayList<String>();

    public String getMyIndexedListClass(int index) {
        return myIndexedListClass.get(index);
    }
    public void setMyIndexedListClass(int index, String element) {
        this.myIndexedListClass.set(index, element);
    }
    public List<String> getMyIndexedListClass() {
        return myIndexedListClass;
    }
    public void setMyIndexedListClass(List<String> 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<PropertyDescriptor> 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;
  }
}

这篇关于自JDK 7以来,Java JDK 8 IndexedPropertyDescriptor已使用List对象进行了更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 17:51