PropertyDescriptorのコンストラクタを呼び出すと、setterが見つからないという例外が発生する問題にハマったのでそのときの解決メモ。
起きたこと
以下のようなクラスを作成していた。
public class HogeBean {
private LocalDate date;
public String getDate(){
if(this.date == null){
return "";
}
return this.date.toString();
}
public void setDate(LocalDate date){
this.date = date;
}
}
上記クラスからPropertyDescriptorを以下のように作成した。
PropertyDescriptor property = new PropertyDescriptor("date", HogeBean.class);
実行するとIntrosectionExceptionが発生し、「Method not found: setDate」というメッセージが表示された。
なぜこうなるのか
setDateメソッドがないといわれているが、その名前のメソッドは存在している。
ということで、PropertyDescriptorの中身を調査した。
コンストラクタはざっくりと以下のような処理を行う。
- まずgetterメソッドを探す。
- isDateという名前で引数の数が0個のメソッドを探す。
- みつからない場合はgetDateという名前で引数の数が0個のメソッドを探す。
- それでもみつからない場合はIntrospectionExceptionをスローする。
- みつかった場合は、戻り値の型を保持しておく。
- 次にsetterメソッドを探す。
- setDateという名前で引数の数が1個で、その型がgetterの戻り値の型と一致するメソッドを探す。
- みつからない場合はIntrospectionExceptionをスローする。
つまり今回の例では、getterの戻り値の型と、setterの引数の型がStringとLocalDateとなっていて、一致しないのが問題だった。
ということで
今回はgetterで日付を文字列に変換するようにしていたが、getterはフィールドをそのまま返却するようにして、変換した値を返却するメソッドは別の名前で定義した方がいいということだった。
public class HogeBean {
private LocalDate date;
public LocalDate getDate(){
return this.date;
}
public String getDateString(){
if(this.date == null){
return "";
}
return this.date.toString();
}
public void setDate(LocalDate date){
this.date = date;
}
}