由ApacheCommon-BeanUtils1.8.3发现的Java的Bug
org.apache.commons.beanutils.BeanUtils.copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException
我实际工程中orig参数是一个实现了泛型接口的类
public class BaseRole implements java.io.Serializable,Sortable<Long> {
// Fields
private Long sort;
...略
public Long getSort() {
return this.sort;
}
public void setSort(Long sort) {
this.sort = sort;
}
}
接口为
public interface Sortable<T> {
public T getSort();
}
这个BaseRole中的sort是无法通过BeanUtils.copyProperties 写入值的
原因是BeanUtils.copyProperties 底层使用了
BeanInfo beanInfo = Introspector.getBeanInfo(BaseRole.class);
PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
而Java在这里是有Bug的
不能完全信任修复速度,1.6.0_05的BUG,我这跑的1.6.0_31仍未修复此问题!!
google 一下 BeanInfo.getPropertyDescriptors problem
第一个就是 sun 的Bug bolg
http://bugs.sun.com/view_bug.do?bug_id=6788525
Bug ID: | 6788525 |
Votes | 1 |
Synopsis | RFE: BeanInfo.getPropertyDescriptors() gets mixed up with generic bridge methods |
Category | java:classes_beans |
Reported Against | |
Release Fixed | |
State | 3-Accepted, request for enhancement |
Priority: | 4-Low |
Related Bugs | |
Submit Date | 23-DEC-2008 |
Description | FULL PRODUCT VERSION : java version "1.6.0_05" Java(TM) SE Runtime Environment (build 1.6.0_05-b13) Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode)
ADDITIONAL OS VERSION INFORMATION : customer Windows XP [versão 5.1.2600]
A DESCRIPTION OF THE PROBLEM : If a JavaBean class has properties that are inherited from a generic superclass, java.beans.BeanInfo will find a PropertyDescriptor corresponding to synthetic bridge methods and not the actual typed methods.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Create a generic superclass with a property (getter/setter pair) whose type is a type parameter. Create a parametrized subclass (a subclass with actual type arguments). Use java.beans.Introspector.getBeanInfo() to get a BeanInfo representing the subclass. Notice that the PropertyDescriptor that would correspond to the property (meaning, it's name is the same as the name of the property) has a type equal to the upper bound of the type parameter in the superclass, where we would expect it to have the corresponding type argument defined on the subclass.
This behavior is likely due to the Introspector finding synthetic bridge methods for the getter and setter instead of the actual methods.
(The Expected and Actual results below refer to the output of the sample code)
EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - class of type class java.lang.Class foo of type class java.lang.String
ACTUAL - class of type class java.lang.Class foo of type class java.lang.Object
REPRODUCIBILITY : This bug can be reproduced always.
---------- BEGIN SOURCE ---------- import java.beans.*;
class Super<T> { public T getFoo() {return null;} public void setFoo(T t) {} }
class Sub extends Super<String> { }
public class Main { public static void main(String[] args) throws IntrospectionException { BeanInfo beanInfo = Introspector.getBeanInfo(Sub.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor prop : propertyDescriptors) { System.out.printf("%s of type %s\n", prop.getName(), prop.getPropertyType()); } } } ---------- END SOURCE ---------- Posted Date : 2008-12-23 13:21:58.0 |
Work Around | N/A |
Evaluation | N/A |
Comments |
One more thing about this bug is that when interface Super<T> do not have set method. And Sub have this set method.
When called BeanInfo beanInfo = Introspector.getBeanInfo(Sub.class);
The PropertyDescriptor for foo do not have write method. But what I expected is although the interface Super do not have set method, but I am asking for the BeanInfo of Sub, its PropertyDescriptor should have writeMethod returned.
This is quite an annoying bug to run into and requires a bit of knowledge of the JLS to understand what is going on. I ran into this problem trying to get annotations of the method and was baffled as to why it wasn't working.
|