2009-05-13 2 views
5

Ich habe vor kurzem hinzugefügt, die RI für JSR305 in mein Projekt und habe Anmerkungen zu meinen Schnittstellen wie dies schon länger:Ist das die korrekte Verwendung von javax.annotation von JSR305?

public interface AccountService 
{ 
    @Nullable AccountResult consolidate(@Nonnull Date from, @Nonnull Date to) 
} 

Im Geist des JSR (wie hier beschrieben), denken Sie, ich bin die Annotationen missbrauchen, indem Sie sie in Schnittstellen verwenden? Ich möchte angeben, dass der Rückgabewert Null sein kann, aber ich denke, die @Nullable gilt mehr für die Methode "Konsolidieren". Ich füge sie nicht zu den Implementierungen hinzu, weil, wenn ich kodiere, der Code für die Schnittstelle mein leitendes Licht ist.

+1

Was wäre eine andere Interpretation einer nullbaren Methode, außer der Bedeutung, die Sie ausdrücken möchten (der Rückgabewert kann null sein)? – Thilo

Antwort

1

Ich denke, es hängt davon ab, warum Sie die Anmerkungen hinzufügen.

Wenn Sie sie nur als Referenz hinzufügen, damit die Implementierer der Schnittstelle Ihr beabsichtigtes Design kennen, dann ist das in Ordnung.

Ich verwende Annotationen für die Transaktionsverarbeitung und Sicherheitsrollenerzwingung, also sind meine Anmerkungen auf der Implementierungsebene. Das Schöne daran ist, dass der AOP-Prozessor in meinem Spring-Container das Vorhandensein dieser oder jener Annotation testen und entsprechende Proxy-Klassen anwenden kann, um beispielsweise eine Transaktionsgrenze zu definieren oder sicherzustellen, dass der Benutzer für einen bestimmten Methodenaufruf berechtigt ist.

Wenn Sie also eine Verarbeitung der Anwesenheit oder Abwesenheit der Anmerkung deaktivieren möchten, vergewissern Sie sich, dass Ihre Implementierung mit Anmerkungen versehen ist. Wenn es nur als Referenz dient, ist es OK, nur die Schnittstelle zu kommentieren.

6

Sie können '@NonNull String' als strikte Unterklasse von String sehen. Schließlich ist jede Nicht-Null-Zeichenfolge definitiv ein 'instanceof' '@Nullable String', aber jede Instanz von '@Nullable String' darf keine Instanz von '@NonNull String' sein (wäre es nicht, wenn wäre null, zum Beispiel).

Wenn Sie es so betrachten, sind @Nullable und @NonNull Typinformationen und daher in den Schnittstellen durchaus sinnvoll. Sie geben den Implementierern an, dass sie null zurückgeben können und dass sie sich keine Gedanken über Eingabe-Nullen machen müssen, und Sie geben Anrufern an, dass sie keine Null übergeben dürfen und dass sie Nullen erwarten sollten.

Natürlich, während dies alles sehr vernünftig ist, erzwingt Vanille javac v1.6 sicherlich keine dieser Regeln die Art, wie es Typsicherheit für tatsächliche Typen erzwingt. Aber man kann träumen, oder man könnte etwas wie PMD oder Findbugs verwenden, um diese Annotationen zu überprüfen.

Die @NonNull- und @Nullable-Annotationen reichen jedoch nicht für ein vollständiges Nullity-Typsystem. Ich weiß nicht wirklich, warum JSR305 dies nicht anspricht, aber es gibt einen dritten Typ: "@MaybeNull". Es würde innerhalb der generischen Parameter auftauchen; woanders hätte es die gleiche Bedeutung wie @Nullable.

public static void addIfNotNull (Liste < @MaybeNull T> liste, @Nullable T item) { if (item! = Null) list.add (item); }

Wenn die Annotation auf dem ersten 'T' ist "@Nullable", dann könnten Sie nicht-Null-Listen in, die für eine ziemlich nutzlose API machen würde. Auf der anderen Seite, wenn es @NonNull war, konnten Sie keine Nullable-Liste übergeben. In der Praxis spielt es keine Rolle, was Sie dort bewegen, es wird (A) nie eine NullPointerException verursachen, und (B) niemals die Annotation verletzen. Du brauchst also eine Möglichkeit, um auszudrücken: Es ist mir egal, ob dieses spezielle 'T' Nullbar ist oder nicht; Ich werde null überprüfen, wenn ich davon lese, und ich werde niemals Nullen schreiben, also spielt es keine Rolle.

Der Unterschied zwischen @MaybeNull und @Nullable ist analog zum Unterschied zwischen '? erweitert Anzahl und Nummer in Generics. Außerhalb von Generika bedeuten sie dasselbe, aber in Generika gibt es einen Unterschied.

Also, halten Sie sich keine Hoffnungen auf einen starren Typcheck in absehbarer Zeit.

@Inherited funktioniert nur für Klassen, aber man könnte sich etwas Ähnliches für annotierte Rückgabetypen und annotierte Parameter vorstellen.

+0

@MaybeNull wurde aus JSR305 verschrottet, soweit ich weiß. Außerdem werden Anmerkungen zu generischen Typen von JSR308 angegeben, die in Java7 verfügbar sein werden. (HINWEIS: Nur diese ** Tatsache **, dass Sie allgemeine Typen mit Anmerkungen versehen können, wird aktiviert, nicht die gesamten Sammlungen vordefinierter Anmerkungen.) –