Интроспекция Java - странное поведение
Ниже приведен небольшой пример, который легко воспроизводит проблему. Поэтому у меня есть переменная типа String, на которой установлено значение по умолчанию. У меня есть 3 метода:
- геттер
- сеттер
- метод удобства, который преобразует строку в boolean
Интроспекция не возвращает getter как readMethod и setter как метод writeMethod. Вместо этого он возвращает метод isTest() как метод readMethod. Установщик пуст.
Из документации я понимаю, что если тип будет логическим, метод "is" имеет более высокий приоритет над get, но тип - String, поэтому не имеет смысла даже искать "is-xxx", метод?
public class Test {
public class Arguments {
private String test = Boolean.toString(true);
public boolean isTest() {
return Boolean.parseBoolean(test);
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
/**
* @param args the command line arguments
*/
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("Setter: " + info.getPropertyDescriptors()[1].getWriteMethod());
PropertyDescriptor descr = new PropertyDescriptor("test", Arguments.class);
System.out.println("T");
}
}
Есть ли кто-нибудь, кто имеет представление об этом?
Дополнительная информация:
- Заказ не изменяет результат. Метод isTest() всегда рассматривается как readMethod
- Если я просто переименую isTest() в bsTest(), он выбирает getter и setter как readMethod и writeMethod. Таким образом, это имеет какое-то отношение к "is-xxx".
Ответы
Ответ 1
Результат, который вы получаете, на самом деле является ожидаемым результатом в соответствии с спецификацией JavaBeans.
Указание пункта 8.3.1 для простых свойств:
Если мы обнаружим совпадающую пару методов get<PropertyName>
и set<PropertyName>
которые принимают и возвращают один и тот же тип, тогда мы рассматриваем эти методы как определяющие свойство чтения-записи, имя которого будет <propertyName>
.
Затем, цитируя пункт 8.3.2 для булевых свойств:
Этот метод is<PropertyName>
может быть предоставлен вместо метода get<PropertyName>
или может быть предоставлен в дополнение к методу get<PropertyName>
.
В любом случае, если метод is<PropertyName>
присутствует для логического свойства, то мы будем использовать метод is<PropertyName>
для чтения значения свойства.
В вашем примере Introspector обнаруживает метод isTest
и getTest
. Поскольку isTest
имеет приоритет над getTest
, он использует isTest
для определения типа свойства test
как boolean
. Но тогда Introspector ожидает, что сеттер будет иметь подпись void setTest(boolean test)
и не найдет его, поэтому метод setter null
.
Важно отметить, что Introspector не читает поля. Он использует подпись методов getter/setter, чтобы определить, какие поля присутствуют, и их соответствующие типы. isTest
подпись метода задает свойство с именем test
типа boolean
, поэтому, независимо от фактического типа test
, Introspector будет считать, что ваш класс имеет свойство boolean test
.
Фактически, для всего Инспектора существует свойство 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());
}
}
Ответ 2
Действительный член совершенно не имеет отношения к Introspector
. Например, вы можете использовать метод getName()
, который возвращает только фиксированный String
, и Introspector найдет его получателем для члена с именем "name". У вас может даже быть сеттер, если член не существует. Вы даже можете предоставить интерфейс для Introspector
, и он будет определять свойства этого, даже если не могут быть какие-либо реальные члены.
Другими словами, свойства определяются наличием методов getter и setter, а не фактическим поиском переменных.