Ich habe eine Klasse mit einer hasField
Funktion, die prüft , ob ein Feld vorhanden ist und nicht null ist , und eine getField
Funktion, die gibt den Wert des Feldes (oder null , wenn nicht vorhanden).
In meinem Code , wenn ich rufe getField
gleich nach Überprüfung hasField
, weiß ich , dass getField nicht null gehen zurück, aber die IDE Inspection ( Constant Bedingungen und Ausnahmen ) nicht weiß , dass. Ich bekomme eine Reihe von Verfahren method name
produzieren kann einNullPointerException
Ich versuche, eine saubere Art und Weise zu finden, diese Warnung zu machen, gehen Sie weg.
Abhilfen
Hier sind einige Abhilfen ich tun könnte, aber ich all diese Hacky finden:
- Surround
getField
mitObjects.requireNotnull
, würde der Code no-op. Würde es vorziehen , nicht das zu tun , wie es der Code etwas weniger lesbar macht. - Unterdrückt Warnungen, wo ich weiß, dass dies sicher ist. Wieder nicht bevorzugt, da dies zu einer Reihe von Orten in unserem Code passieren wird.
- Warnungen ignorieren. In diesem Fall könnten wir legit Warnungen verpassen, nur weil Warnungen Abschnitt zu laut sein.
ideale Lösung
Würde ich in der Lage sein , die Warnungen in einer solchen Art und Weise irgendwie einrichten , dass , wenn hasField
wahr ist, dann getField
wird eine nicht-null zurück? Ich sah in JetBrains Contract Annotations aber tun , was ich hier wollen scheint darüber hinaus zu sein , was mit @Contract unterstützt wird
Codebeispiel
Hier ist ein Mindestarbeitscodebeispiel, das das Problem veranschaulicht:
import javax.annotation.Nullable;
public class Hello {
private Hello(){}
public static void main(String[] args) {
TestClass test1 = new TestClass(null);
if (test1.hasSample()) {
System.out.println(test1.getSample().equals("abc"));
}
}
}
class TestClass {
private final String sample;
TestClass(String field) { this.sample = field; }
boolean hasSample() { return sample != null; }
@Nullable public String getSample() { return sample; }
}
Ich erhalte die folgende Warnung
Methodenaufruf
equals
kann produzierenNullPointerException
Ich würde wollen, im Idealfall der Lage sein, IDE zu sagen, dass getSample nicht null ist, wenn hasSample wahr ist.
Offenlegung Ich bin IntelliJ IDEA Entwickler verantwortlich für dieses Subsystem
Nein, es ist nicht möglich. Es gibt keine bessere Lösung als mögliche Abhilfen Sie bereits aufgeführt sind, vorausgesetzt, dass Sie nicht die API ändern. Das nächste, was wir haben, ist der inlining sehr trivial Methoden. Aber es funktioniert nur, wenn:
- Die Methoden mögen
hasSample()
undgetSample()
sind aus der gleichen Klasse aufgerufen - Die genannten Methoden können nicht außer Kraft gesetzt werden (privat / static / final / finale Klasse deklariert)
Zum Beispiel funktioniert diese Funktion in dem folgenden Code:
final class TestClass { // if final is removed, the warning will appear again
private final String sample;
TestClass(String field) { this.sample = field; }
boolean hasSample() { return sample != null; }
@Nullable
public String getSample() { return sample; }
@Override
public String toString() {
if (hasSample()) {
return "TestClass: "+getSample().trim(); // no warning on trim() invocation here
}
return "TestClass";
}
}
Denn jetzt kann ich nur vorschlagen Ihre APIs Optionals wie dieser Refactoring:
import java.util.Optional;
public class Hello {
private Hello(){}
public static void main(String[] args) {
TestClass test1 = new TestClass(null);
test1.getSample().ifPresent(s -> System.out.println(s.equals("abc")));
// or fancier: test1.getSample().map("abc"::equals).ifPresent(System.out::println);
}
}
final class TestClass {
private final String sample;
TestClass(String field) { this.sample = field; }
public Optional<String> getSample() { return Optional.ofNullable(sample); }
}