У меня есть класс с hasField
функцией , которая проверяет , является ли поле присутствует и не равно нулю, и getField
функция , которая возвращает значение поля (или нуль , если нет).
В моем коде , когда я вызываю getField
сразу после проверки hasField
, я знаю , что ПолучитьПолеЗаголовка не собирается возвращать нуль, но IDE Inspection ( постоянные условия и исключения ) не знает , что. Я получаю кучу метод method name
может производитьNullPointerException
Я пытаюсь найти чистый способ сделать это предупреждение уйти.
обходные
Вот некоторые обходные пути я мог бы сделать, но я нахожу все эти Hacky:
- Surround
getField
сObjects.requireNotnull
, код не будет оп. Предпочли бы не делать это , как это делает код немного менее читабельным. - Подавить предупреждения, когда я знаю, что это безопасно. Опять же не является предпочтительным, так как это будет происходить на кучу мест в коде.
- Игнорировать предупреждения. В этом случае мы могли бы пропустить предупреждения законных только потому, что предупреждения раздел будет слишком шумно.
Идеальное решение
Смогу ли я каким - то образом настроить предупреждения таким образом , что , если hasField
это правда, то getField
вернет ненулевой? Я посмотрел в JetBrains контракта аннотаций , но делать то , что я хочу здесь , кажется, за то , что поддерживается @Contract
Пример кода
Вот минимальный рабочий образец кода, который демонстрирует проблему:
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; }
}
Я получаю следующее предупреждение
Способ вызова
equals
может привести кNullPointerException
Я бы в идеале хотели бы быть в состоянии сказать, что IDE getSample не равно нулю, когда hasSample верно.
Раскрытие Я IntelliJ IDEA разработчик отвечает за эту подсистему
Нет, это не представляется возможным в настоящее время. Там нет лучшего решения, чем возможные обходные пути вы уже перечисленных, при условии, что вы не можете изменить API. Ближе всего мы имеем это встраивание очень тривиальных методов. Тем не менее, он работает только тогда, когда:
- Эти методы , как
hasSample()
иgetSample()
вызываются из того же класса - Вызываемые методы не могут быть переопределены (частный / статический / Окончательный / объявлен в окончательном классе)
Например, эта функция работает в следующем коде:
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";
}
}
На данный момент, я могу только предложить рефакторинга свои API, чтобы OPTIONALS как это:
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); }
}