Ich kann das sehen @Nullable
und @Nonnull
Anmerkungen könnten hilfreich sein, um NullPointerException
s zu verhindern, aber sie verbreiten sich nicht sehr weit.
- Die Effektivität dieser Anmerkungen nimmt nach einer Indirektionsebene vollständig ab. Wenn Sie also nur einige hinzufügen, breiten sie sich nicht sehr weit aus.
- Da diese Anmerkungen nicht gut durchgesetzt werden, besteht die Gefahr, dass ein mit gekennzeichneter Wert
@Nonnull
nicht null ist und folglich keine Nullprüfungen durchgeführt werden.
Der folgende Code verursacht einen Parameter mit markiert @Nonnull
werden , null
ohne irgendwelche Beschwerden zu erhöhen. Es wirft ein, NullPointerException
wenn es ausgeführt wird.
public class Clazz {
public static void main(String[] args){
Clazz clazz = new Clazz();
// this line raises a complaint with the IDE (IntelliJ 11)
clazz.directPathToA(null);
// this line does not
clazz.indirectPathToA(null);
}
public void indirectPathToA(Integer y){
directPathToA(y);
}
public void directPathToA(@Nonnull Integer x){
x.toString(); // do stuff to x
}
}
Gibt es eine Möglichkeit, diese Anmerkungen strenger durchzusetzen und / oder weiter zu verbreiten?
java
annotations
nullpointerexception
nullable
code-standards
Mike Rylander
quelle
quelle
@Nullable
oder@Nonnull
, aber wenn sie es wert sind, ist es sehr "wahrscheinlich, Debatte zu erbitten"@Nonnull
beim Aufrufen einer@Nonnull
Methode mit einer nullbaren Variablen eine Umwandlung in zu erfordern . Natürlich ist das Casting mit einer Annotation in Java 7 nicht möglich, aber Java 8 bietet die Möglichkeit, Annotationen auf die Verwendung einer Variablen anzuwenden, einschließlich Casts. So kann dies in Java 8 implementiert werden.(@NonNull Integer) y
syntaktisch möglich, aber ein Compiler darf keinen bestimmten Bytecode basierend auf der Annotation ausgeben. Für Laufzeit-Assertions sind winzige Hilfsmethoden ausreichend, wie in bugs.eclipse.org/442103 (z. B.directPathToA(assertNonNull(y))
) beschrieben - aber wohlgemerkt , dies hilft nur, schnell zu scheitern. Der einzig sichere Weg besteht darin, eine tatsächliche Nullprüfung durchzuführen (und hoffentlich eine alternative Implementierung im Zweig else).@Nonnull
und@Nullable
Sie sprechen, da es mehrere ähnliche Anmerkungen gibt (siehe diese Frage ). Sprechen Sie über die Anmerkungen im Paketjavax.annotation
?Antworten:
Kurze Antwort: Ich denke, diese Anmerkungen sind nur für Ihre IDE nützlich, um Sie vor potenziell Nullzeigerfehlern zu warnen.
Wie im Buch "Code bereinigen" erwähnt, sollten Sie die Parameter Ihrer öffentlichen Methode überprüfen und auch die Überprüfung von Invarianten vermeiden.
Ein weiterer guter Tipp ist, niemals Nullwerte zurückzugeben, sondern stattdessen das Null-Objektmuster zu verwenden.
quelle
Optional
Typ anstelle vonnull
Optional
und nullable in diesem Fall besteht darin, dassOptional
besser kommuniziert wird, dass dieser Wert absichtlich leer sein kann. Sicherlich ist es kein Zauberstab und in der Laufzeit kann es genauso fehlschlagen wie eine nullfähige Variable. Allerdings ist der API-Empfang durch ProgrammiererOptional
meiner Meinung nach besser .Abgesehen von Ihrer IDE, die Ihnen Hinweise gibt, wenn Sie
null
an Methoden übergeben, bei denen erwartet wird, dass das Argument nicht null ist, gibt es weitere Vorteile:Dies kann dazu beitragen, dass Ihr Code besser gewartet werden kann (da Sie ihn nicht benötigen
null
Überprüfungen ) und weniger fehleranfällig ist.quelle
assert
. Ich finde@Nullable
und@Nonnull
nützliche Ideen zu sein, aber ich würde mehr Kraft hinter sie mögen, anstatt uns über hypothesizing , was man konnte mit ihnen zu tun, die noch Blätter die Möglichkeit , nichts zu tun mit ihnen öffnen.Ich denke, diese ursprüngliche Frage weist indirekt auf eine allgemeine Empfehlung hin, dass eine Laufzeit-Nullzeigerprüfung weiterhin erforderlich ist, obwohl @NonNull verwendet wird. Siehe folgenden Link:
Die neuen Typanmerkungen von Java 8
Im obigen Blog wird empfohlen, dass:
quelle
Beim Kompilieren des Originalbeispiels in Eclipse mit Konformität 1.8 und aktivierter annotationsbasierter Nullanalyse wird folgende Warnung angezeigt:
Diese Warnung ist analog zu den Warnungen formuliert, die Sie erhalten, wenn Sie generierten Code mit Legacy-Code unter Verwendung von Rohtypen mischen ("ungeprüfte Konvertierung"). Wir haben hier genau die gleiche Situation: Methode
indirectPathToA()
hat eine "Legacy" -Signatur, da sie keinen Nullvertrag angibt. Tools können dies leicht melden, sodass sie Sie durch alle Gassen jagen, in denen Nullanmerkungen weitergegeben werden müssen, aber noch nicht.Und wenn man einen cleveren benutzt
@NonNullByDefault
wir wir das nicht jedes Mal sagen.Mit anderen Worten: Ob sich Nullanmerkungen "sehr weit ausbreiten" oder nicht, hängt möglicherweise von dem von Ihnen verwendeten Tool ab und davon, wie streng Sie alle vom Tool ausgegebenen Warnungen beachten. Mit TYPE_USE-Nullanmerkungen haben Sie endlich die Möglichkeit, sich vom Tool vor jeder möglichen NPE in Ihrem Programm warnen zu lassen , da die Nullheit zu einer intrisischen Eigenschaft des Typsystems geworden ist.
quelle
Ich bin damit einverstanden, dass sich die Anmerkungen "nicht sehr weit verbreiten". Ich sehe jedoch den Fehler auf der Seite des Programmierers.
Ich verstehe die
Nonnull
Anmerkung als Dokumentation. Die folgende Methode drückt aus, dass (als Voraussetzung) ein Nicht-Null-Argument erforderlich istx
.Das folgende Codefragment enthält dann einen Fehler. Die Methode ruft auf,
directPathToA()
ohne zu erzwingen, dass siey
nicht null ist (das heißt, sie garantiert nicht die Vorbedingung der aufgerufenen Methode). Eine Möglichkeit besteht darin, auch eineNonnull
Anmerkung hinzuzufügenindirectPathToA()
(Weitergabe der Vorbedingung). Möglichkeit zwei besteht darin, die Nichtigkeit vony
in zu überprüfenindirectPathToA()
und den Aufruf vondirectPathToA()
when zu vermeiden, wenny
null ist.quelle
@Nonnull
zu habenindirectPathToA(@Nonnull Integer y)
ist meiner Meinung nach eine schlechte Praxis: Sie müssen die Weitergabe auf dem vollständigen Aufrufstapel beibehalten (wenn Sie also einennull
Check-in hinzufügendirectPathToA()
, müssen Sie im vollständigen Aufrufstapel@Nonnull
durch ersetzen@Nullable
). Dies wäre ein großer Wartungsaufwand für große Anwendungen.In meinen Projekten aktiviere ich die folgende Option in der Codeüberprüfung "Konstante Bedingungen und Ausnahmen":
Schlagen Sie eine Annullation @Nullable für Methoden vor, die möglicherweise null zurückgeben und nullfähige Werte melden, die an nicht annotierte Parameter übergeben werden
Wenn diese Option aktiviert ist, werden alle nicht mit Anmerkungen versehenen Parameter als nicht null behandelt. Daher wird bei Ihrem indirekten Aufruf auch eine Warnung angezeigt:
Für noch stärkere Überprüfungen ist das Checker Framework möglicherweise eine gute Wahl (siehe dieses nette Tutorial .
Hinweis : Ich habe das noch nicht verwendet und es kann Probleme mit dem Jack-Compiler geben: siehe diesen Fehlerbericht
quelle
In Java würde ich den optionalen Typ von Guava verwenden . Als tatsächlicher Typ erhalten Sie Compiler-Garantien für seine Verwendung. Es ist einfach, es zu umgehen und ein zu erhalten
NullPointerException
, aber zumindest die Signatur der Methode kommuniziert klar, was sie als Argument erwartet oder was sie zurückgeben könnte.quelle
java.util.Optional
anstelle der Guava-Klasse. Einzelheiten zu den Unterschieden finden Sie in den Notizen / im Vergleich von Guava .Wenn Sie Kotlin verwenden, werden diese Annotationen zur Nullfähigkeit in seinem Compiler unterstützt und Sie können keine Null an eine Java-Methode übergeben, für die ein Argument ungleich Null erforderlich ist. Obwohl diese Frage ursprünglich auf Java ausgerichtet war, erwähne ich diese Kotlin-Funktion, da sie speziell auf diese Java-Annotation ausgerichtet ist und die Frage lautete: "Gibt es eine Möglichkeit, diese Annotationen strenger durchzusetzen und / oder weiter zu verbreiten?" Durch diese Funktion werden diese Anmerkungen strenger erzwungen .
Java-Klasse mit
@NotNull
AnnotationKotlin-Klasse, die die Java-Klasse aufruft und null für das mit @NotNull annotierte Argument übergibt
Kotlin-Compilerfehler beim Erzwingen der
@NotNull
Anmerkung.Siehe: http://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations
quelle
myString.hashCode()
wird jedoch weiterhin NPE ausgelöst, auch wenn dies@NotNull
nicht im Parameter hinzugefügt wird. Was ist also spezifischer beim Hinzufügen?Seit der neuen Java 8-Funktion Optional sollten Sie @Nullable oder @Notnull nicht mehr in Ihrem eigenen Code verwenden . Nehmen Sie das folgende Beispiel:
Es könnte umgeschrieben werden mit:
Wenn Sie eine Option verwenden, müssen Sie nach Nullwerten suchen . Im obigen Code können Sie nur durch Aufrufen von auf den Wert zugreifen
get
Methode .Ein weiterer Vorteil ist, dass der Code besser lesbar wird . Mit Java 9 ifPresentOrElse könnte die Funktion sogar wie folgt geschrieben werden:
quelle
Optional
gibt es immer noch viele Bibliotheken und Frameworks, die diese Anmerkungen verwenden, sodass es nicht möglich ist, alle Ihre Abhängigkeiten durch Versionen zu aktualisieren / zu ersetzen, die für die Verwendung von Optionals aktualisiert wurden.Optional
kann jedoch in Situationen helfen, in denen Sie null in Ihrem eigenen Code verwenden.