- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这个问题看起来很尴尬,但我们在检索 javabean 的 PropertyDescriptors 时遇到了一个奇怪的行为。下面是一段简单代码在 1.6、1.7 和 1.8 上的执行结果,编译时符合 1.6 标准。
Java 1.6 执行:
java.beans.PropertyDescriptor@4ddc1428 <- 不重要java.beans.IndexedPropertyDescriptor@7174807e <- 是的,我有一个索引属性
Java 1.7 执行:
java.beans.PropertyDescriptor[名称=类; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()] <- 不重要java.beans.IndexedPropertyDescriptor[名称=值; indexedPropertyType=class java.lang.String; indexedReadMethod=public java.lang.String JavaBean.getValues(int)] <- 是的,我有一个索引属性
Java 1.8 执行:
java.beans.PropertyDescriptor[名称=类; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()] <- 不重要java.beans.PropertyDescriptor[名称=值; propertyType=接口(interface)java.util.List; readMethod=public java.util.List JavaBean.getValues()] <- 哎哟!这不再是索引属性!
为什么变了?
javabean 规范说明了如何使用索引访问属性。并没有说必须使用数组作为索引属性的容器。我错了吗?
我阅读了规范,第 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);
}
}
}
最佳答案
来自 JavaBeans 1.01 规范,第 7.2 节“索引属性”:
A component may also expose an indexed property as a single array value.
第 8.3 节描述了设计模式 introspection在没有显式 BeanInfo 的情况下识别。第 8.3.3 节说只有数组属性会触发索引属性的自动识别。
你在技术上是正确的;使用数组不是强制性的。但如果你不这样做,规范说你必须提供你自己的 BeanInfo 来将该属性公开为索引属性。
所以您的问题的答案是:是的,Java 1.8 符合 JavaBean 规范。
我不确定为什么支持 List 属性。也许 future 的 JavaBeans 规范会支持它们,但现在已经被撤销。
关于您的最后一个问题:我认为您必须为每个具有 List 属性的类创建一个 BeanInfo 类。我希望您可以创建一个通用父类(super class)以使其更容易,例如:
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;
}
}
关于java - JRE 1.8 是否仍然是 JavaBean 规范提示 Indexed PropertyDescriptor?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34726164/
我们正在使用 DynamicObject 创建动态属性,但随后我们想使用 PropertyGrid 来显示和编辑这些属性。 首先,我找到了this文章和这个one .我尝试使用第二篇文章的代码,但以更
我有一个数组字段的 PropertyDescriptor,如下所示。 Foo[] fooArray; 如何获取 Foo 的 PropertyDescriptor,以便能够获取该类的 getter 和
我有一组自定义 PropertyDescriptor,我也想添加类别,以便它们以更有条理的方式显示在 PropertyGrid 中。我希望每种类型的 PropertyDescriptor 都属于特定的
如何获取当前属性的 PropertyDescriptor?例如: [MyAttribute("SomeText")] public string MyProperty { get{....}
我正在通过实现 ICustomTypeDescriptor 自定义对象类型在 PropertyGrid 中的显示方式。我允许用户创建他们自己的自定义属性,这些属性存储在单个键和值字典中。我能够为这些值
.NET 上的 PropertyType 和 ComponentType 有什么区别 PropertyDescriptor ? 文档并没有真正解释 PropertyType When overridd
我有一个简单的 Windows 窗体应用程序,它使用 DataGridView绑定(bind)到 BindingList<>我的自定义对象 (MCO)。 我还实现了一个自定义 TypeDescript
如果我有: class A { public virtual string Owner { get; set; } } class B : A { public override st
我对这个方法的细节很感兴趣。如何以及通过什么来跟踪属性(property)的值(value)变化? 最佳答案 Andrew Smith 有一个 cool blog post关于它,我认为它会对您有所帮
我是 WPF 的新手,我正在尝试自定义一些数据网格以以可读的方式显示数据。我看过this article ,我想知道 - 最后将 PropertyDescriptor 属性转换为两个类,使用 as 关
是否有用于为属性设置默认 PropertyDescriptor 的属性?我只想给属性添加一个属性并指定 PropertyDescriptor。然后将创建 PropertyDescriptor 的实例。
我正在尝试在 WCF 服务中进行一些验证,为此我正在使用 WCFDataAnnotations我通过 this post 找到的 问题是它不能递归验证,所以对于嵌套对象它不起作用。这么说吧 [Data
我正在通过 获取有关类(class)的信息 Introspector.getBeanInfo(this.getClass()).getPropertyDescriptors() 然后通过调用 prop
我正在尝试检查一个属性是否应用了 DataMemberAttribute(使用 TypeDescriptor) 这是我现在拥有的: PropertyDescriptor targetProp = ta
我一直在努力让自定义 PropertyDescriptors 以我想要的方式使用 PropertyGrid。 前提: 我有一个名为“Animal”的类,其中包含属性 Age , Type , Loca
使用为 IsReadOnly() 方法返回值的 PropertyDescriptor 和与 ReadOnlyAttribute 关联的有什么区别>? 最佳答案 主要区别在于,如果您提供自己的 Prop
PropertyDescriptor是自定义属性描述符可以从中继承的抽象类。该类有一个 IsBrowsable 属性,根据 MSDN: Gets a value indicating whether
我有一些代码可以枚举一个对象并根据它的 ValidationAttribute 记录它的任何错误。 当它找到它们时,我希望创建一个名为 RuleViolations 的自定义类的集合。 RuleVio
我正在实现自定义 ModelBinder,我试图用 PropertyDescriptor.SetValue 设置一个属性我不明白为什么它不起作用。 对于某些复杂属性,未设置值但不会引发异常。该属性仍然
各位 SO 成员大家好! 我正在为 Eclipse RCP 应用程序编写一个插件,当我从 TreeViewer 选择一行时,它的属性会出现在属性 View 中。 最初我在寻找一种可以将某些属性设置为只
我是一名优秀的程序员,十分优秀!