Als ich vor kurzem an einem Dienstprogramm zum Klonen von Beans gearbeitet habe (mehr dazu ein andermal), blieb ich eine Zeit lang bei einem unerwarteten Verhalten von java.beans.Introspector hängen. Ich kenne nicht viele Leute, die diese Klasse direkt verwenden, aber sie wird unter anderem von den Apache BeanUtils stark genutzt. Wenn Sie diese also verwenden, könnten Sie trotzdem auf dieses Problem stoßen.
Das Problem tritt auf, wenn Sie in Ihren Klassen Bean-Eigenschafts-Accessors überschrieben haben.
Nehmen wir zum Beispiel an, Sie haben eine Basisklasse NumberHolder:
public class NumberHolder {
private Number number;
public Number getNumber() { return number; }
public void setNumber(Number number) { this.number = number; }
}
Nehmen wir an, Sie wissen, dass der NumberHolder in einem bestimmten Kontext in Ihrer Anwendung immer einen Long enthalten wird. Dann könnten Sie weiterhin
Long long = (Long) myHolder.getNumber();
aber das ist ziemlich hässlich. Sie könnten also einen LongHolder erstellen:
public class LongHolder extends NumberHolder {
@Override
public Long getNumber() { return (Long) super.getNumber(); }
}
Die entscheidende Frage ist nun: Ist die Eigenschaft number von LongHolder beschreibbar oder nicht? Sie hat zwar einen Setter, der eine Number akzeptiert , und einen Getter, der eine Number (Unterklasse) zurückgibt, aber andererseits hat sie keinen Setter, der eine Long akzeptiert, und die Eigenschaft selbst ist auch keine Long.[Anmerkung: Ich bin nicht mehr ausreichend mit den Feinheiten der Beans-Spezifikation vertraut, um sicher zu sein, ob das Überschreiben der getNumber()-Methode nicht einen Verstoß darstellt. Jeder Kommentar zu diesem Thema wäre interessant.]Wie auch immer, man würde erwarten, dass die Antwort entweder "ja" oder "nein" lautet. Leider scheint die Realität jedoch so auszusehen: "Nun, es kommt darauf an."Hängt in der Tat davon ab, in welcher Stimmung Class.getDeclaredMethods ist, d.h. in welcher Reihenfolge es die beiden getNumber()-Methoden von LongHolder zurückgibt. Introspector ruft diese Methoden ab, um mögliche Getter und Setter miteinander zu verbinden und so die Lese-/Schreibbarkeit der Bean-Eigenschaften zu bestimmen.
Wenn LongHolder.getNumber zuerst kommt, wird es in der Datenstruktur des Introspectors durch NumberHolder.getNumber "überschrieben", für das ein passender Setter gefunden wird (richtiger Name, gleicher Typ), so dass die Eigenschaft beschreibbar ist.
Wenn jedoch NumberHolder.getNumber zuerst kommt... nun, Sie können sich sicher denken, was passiert: Es wird kein passender Setter gefunden (es gibt keine setNumber(Long)-Methode in einer der beiden Klassen) und daher ist die Eigenschaft nicht beschreibbar.
...und da die Reihenfolge der Methoden, die von Class.getDeclaredMethods zurückgegeben werden, als unbestimmt dokumentiert ist, handelt es sich um einen Fehler(6807471, in der Tat).
Wenn Sie also irgendwo in Ihrem Code Eigenschafts-Accessors überschreiben, sollten Sie dies bedenken.
Es sieht übrigens so aus, als gäbe es bereits viele Probleme im Zusammenhang mit der unbestimmten Reihenfolge von Class.getDeclaredMethods. In den Fehlerberichten zu einigen dieser Probleme wird sehr detailliert auf die Schwierigkeit eingegangen, eine Reihenfolge festzulegen. Dennoch bin ich überrascht, dass dieses Problem noch nicht angegangen wurde.