Tengo una clase con una hasField
función que comprueba si un campo está presente y no nulo, y una getField
función que devuelve el valor del campo (o NULL si no está presente).
En mi código cuando llamo a getField
la derecha después de la comprobación hasField
, sé que getField no va a volver nula, pero la Inspección IDE ( condiciones constantes y excepciones ) no lo sabe. Consigo un montón de método method name
puede producir unaNullPointerException
Estoy tratando de encontrar una manera limpia para hacer esta advertencia desaparezca.
soluciones provisionales
Aquí hay algunas soluciones que podía hacer, pero me parece todo esto hacky:
- Envolvente
getField
conObjects.requireNotnull
, el código sería no-op. Preferiría no hacerlo, ya que hace que el código un poco menos legible. - Suprimir las advertencias donde sé que esto es seguro. Una vez más no se prefiere ya que esto va a suceder en un montón de lugares en nuestro código.
- No haga caso de las advertencias. En este caso puede que hayamos perdido advertencias de fiar sólo porque la sección advertencias será demasiado ruidoso.
Solución ideal
Me gustaría ser capaz de establecer alguna manera las advertencias de tal manera que si hasField
es cierto, entonces getField
devolverá un no nulo? Miré en JetBrains Contrato Anotaciones pero haciendo lo que quiero aquí parece estar más allá de lo que está apoyado con @Contract
código de ejemplo
He aquí un ejemplo de código de trabajo mínimo que demuestra el problema:
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; }
}
Me da la siguiente advertencia
Método de invocación
equals
puede producirNullPointerException
Me idealmente quiero ser capaz de decir IDE que getSample no es nulo cuando hasSample es cierto.
Divulgación estoy IntelliJ IDEA desarrollador responsable de este subsistema
No, no es posible ahora. No hay mejor solución que posibles soluciones que ya enumeradas, en el supuesto de que no se puede cambiar la API. Lo más cercano que tenemos es la expansión en línea de métodos muy triviales. Sin embargo, sólo funciona si:
- Los métodos como
hasSample()
ygetSample()
se llaman de la misma clase - Los llamados métodos no pueden ser anulados (/ estática / / final privado declarado en la clase final)
Por ejemplo, esta característica funciona en el siguiente código:
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";
}
}
Por ahora, sólo puedo sugerir Refactorizando las APIs para Opcionales como este:
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); }
}