Java内省-奇怪的行为
下面的代码是一个很容易重现问题的小示例。所以我有一个字符串类型的变量,在它上面设置了一个默认值。我有三种方法:Java内省-奇怪的行为,java,javabeans,introspection,Java,Javabeans,Introspection,下面的代码是一个很容易重现问题的小示例。所以我有一个字符串类型的变量,在它上面设置了一个默认值。我有三种方法: 吸气剂 塞特 将字符串转换为布尔值的便利方法 内省不会将getter作为readMethod返回,将setter作为writeMethod返回。相反,它返回isTest()方法作为readMethod。setter是空的 从文档中我了解到,如果类型是布尔值,“is”方法的优先级高于get,但是类型是String,所以即使查找“is xxx”方法也没有意义 有没有人对此有所了解 其他
- 吸气剂
- 塞特
- 将字符串转换为布尔值的便利方法
实际成员与
内省者
完全无关。例如,您可以有一个getName()
方法,该方法只返回一个固定的字符串
,内省者会发现它是名为“name”的成员的getter。如果成员不存在,您甚至可以拥有setter。您甚至可以为内省器提供一个接口,它将根据该接口确定属性,即使没有任何真正的成员
换句话说,属性是由getter和setter方法的存在而不是通过实际搜索变量来确定的。根据
引用第8.3.1段中的简单特性:
如果我们发现一对匹配的get
和set
方法
接受并返回相同类型,那么我们将这些方法视为定义一个名为
的读写属性
然后,引用第8.3.2段中的布尔属性:
可以提供此is
方法来代替get
方法,也可以在get
方法之外提供此方法
在任何一种情况下,如果布尔属性存在is
方法,那么我们将使用is
方法读取属性值
从您的示例中,内省器同时检测isTest
和getTest
方法。由于isTest
的优先级高于getTest
,因此它使用isTest
将test
属性的类型确定为boolean
。但是,内省者希望setter拥有签名void setTest(boolean test)
,但它没有找到它,因此setter方法是null
需要注意的是,内省者不会读取字段。它使用getter/setter方法的签名来确定存在哪些字段及其对应的类型<代码> istest方法签名指定类型为<代码> test <代码>的类型<代码>布尔,因此,无论实际代码类型<代码>测试>代码>,内省者都会考虑您的类具有一个属性“代码>布尔测试 < < /P>”。
事实上,对于所有内省者来说,属性test
可能根本不存在!您可以通过以下代码说服自己:
class Test {
public class Arguments {
public boolean isTest() {
return true;
}
}
public static void main(String[] args) throws IntrospectionException {
BeanInfo info = Introspector.getBeanInfo(Arguments.class);
System.out.println("Getter: " + info.getPropertyDescriptors()[1].getReadMethod());
System.out.println("Name of property: " + info.getPropertyDescriptors()[1].getName());
}
}
如果在类的末尾声明isTest
方法,会发生什么?这可能是因为这是第一次出现,所以它被识别为布尔值,因此setter与类型String不匹配。不,这没有意义,但显然这是他们决定的(或者这是一个bug)。除了停止用字符串表示布尔值外,您对此无能为力:DI在初始文本中添加了更多信息。顺序对结果没有影响。我同意Tunaki的观点,如果你正在做一些元编程,你可以用一些参数强制它按照你的意愿工作:PropertyDescriptor descr=newpropertydescriptor(“test”,Arguments.class,“getTest”,“setTest”)
您提到“它使用isTest将测试属性的类型确定为boolean”,但测试类型明确定义为String。还是因为方法的返回值是布尔值而将类型定义为布尔值?@Quirexx内省者不读取字段。它使用getter/setter方法的签名来确定存在哪些字段及其对应的类型isTest
signature为名为boolean类型的“test”的属性指定,而不考虑“test”的实际类型,因此它只查看方法并遵循JavaBeans命名约定来确定属性。如果你这样看,结果确实是正确的。现在它有意义了。谢谢
class Test {
public class Arguments {
public boolean isTest() {
return true;
}
}
public static void main(String[] args) throws IntrospectionException {
BeanInfo info = Introspector.getBeanInfo(Arguments.class);
System.out.println("Getter: " + info.getPropertyDescriptors()[1].getReadMethod());
System.out.println("Name of property: " + info.getPropertyDescriptors()[1].getName());
}
}