3873 votos

Evitar "!= null" declaraciones en Java?

Yo trabajo con Java largo de todo el día. El más usado en el lenguaje (fragmento de código) estoy de programación en Java, es para probar si un object != null antes de que yo lo uso. Esto es para evitar un NullPointerException. Puedo encontrar el código muy feo y se convierte en ilegible.

Hay una buena alternativa para evitar este fragmento de código?

Actualización: Pan, no fui claro con mi pregunta. Quiero hablar de la necesidad de poner a prueba cada objeto si desea acceder a un campo o método de este objeto. Por ejemplo:

...
if (someobject != null) {
    someobject.doCalc();
}
...

En este caso voy a evitar un NullPointerException, y no sé exactamente si el objeto es null o no. Así que mi código de obtener salpicada con estas pruebas.

No obstante muchas gracias por sus respuestas, tengo un montón de nueva visión.

2568voto

cletus Puntos 276888

Esto me suena como una razonablemente problema común que junior intermedio, los desarrolladores tienden a enfrentar en algún momento: no lo saben o no confiar en los contratos están participando y a la defensiva comprobación general para los valores null. Además, al escribir su propio código, que tienden a confiar en la devolución de los valores null para indicar que algo por lo que requiere la persona que llama a la comprobación de valores null.

Para decirlo de otra manera, hay dos instancias donde comprobación de nulos:

  1. Donde null es una respuesta válida en los términos del contrato; y

  2. Donde esto no es una respuesta válida.

(2) es muy fácil. Utilice assert afirmaciones (aserciones) o permitir que el fracaso (por ejemplo, NullPointerException). Las afirmaciones que están altamente subutilizada Java característica que se añadió en la versión 1.4. La sintaxis es:

assert *<condition>*

o

assert *<condition>* : *<object>*

donde <object>s' toString() de salida será incluido en el error.

Un assert declaración arroja una Error (AssertionError) si la condición no es verdadera. De forma predeterminada, Java ignora afirmaciones. Puede habilitar las afirmaciones realizadas por pasar la opción -ea a JVM. Usted puede activar y desactivar afirmaciones para clases individuales y paquetes. Esto significa que usted puede validar el código con las afirmaciones durante el desarrollo y pruebas, y deshabilitar en un entorno de producción, aunque en mis pruebas ha mostrado casi nada de impacto en el rendimiento de afirmaciones.

No uso de afirmaciones en este caso está bien porque el código se acaba de fallar, que es lo que va a suceder si el uso de afirmaciones. La única diferencia es que con afirmaciones que podría suceder más tarde, en una más-de manera significativa y, posiblemente, con la información adicional, la cual puede ayudar a averiguar por qué ocurrió si usted no esperaba.

(1) es un poco más difícil. Si usted no tiene ningún control sobre el código que usted está llamando, a continuación, usted está atascado. Si es null es una respuesta válida, tienes que comprobarlo.

Si es código que hacer el control, sin embargo (y esto es a menudo el caso), entonces es una historia diferente. Evitar el uso de valores nulos como una respuesta. Con los métodos que devuelven las colecciones, es muy fácil: volver vacíos de colecciones (o matrices) en lugar de valores nulos casi todo el tiempo.

Con los no-colecciones de las que podrían ser más difíciles. Considerar esto como un ejemplo: si usted tiene estas interfaces:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

donde Analizador toma cruda de entrada de usuario y encuentra algo que hacer, tal vez si se está implementando una interfaz de línea de comandos para algo. Ahora usted puede hacer el contrato, que devuelve null si no hay una acción apropiada. Que conduce a la comprobación de nulos que estás hablando.

Una solución alternativa es no devolver null y en lugar de utilizar los Objetos Nulos patrón:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Comparar:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

a

ParserFactory.getParser().findAction(someInput).doSomething();

que es un mucho mejor diseño, porque lleva a un código más conciso.

Dicho esto, tal vez es completamente apropiado que el findAction() método para producir una Excepción con un significativo mensaje de error, especialmente en este caso donde usted está confiando en la entrada del usuario. Sería mucho mejor para el findAction método para producir una Excepción que para el método de llamada a volar con un simple NullPointerException con ninguna explicación.

try{
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

O si usted piensa que el try/catch mecanismo es demasiado feo, en lugar de no Hacer Nada de tu acción predeterminada que se debe proporcionar información al usuario.

public Action findAction(final String userInput){
    /* Code to return requested Action if found */
    return new Action(){
        public void doSomething(){
            userConsole.err("Action not found: "+userInput);
        }
    }
}

594voto

Luca Molteni Puntos 2328

Si usted (o para la planificación de uso) de JetBrains Idea, un ide de Java, puede utilizar algunas anotaciones desarrollado por ellos.

Básicamente, tienes @Nullable y @NotNull.

Se puede utilizar en el método y los parámetros, como este:

@NotNull public static String helloWorld() {
    return "Hello World";
}

o

@Nullable public static String helloWorld() {
    return "Hello World";
}

El segundo ejemplo no compile (Idea).

Cuando se utiliza la primera HelloWorld() de la función en otro trozo de código:

public static void main(String[] args)
{
    if(helloWorld() != null) {
        System.out.println(helloWorld());
    } 
}

Ahora, la idea compilador le dirá que el cheque es inútil, ya que el HelloWorld() la función no devuelve null, nunca.

Mediante el parámetro

void someMethod(@NotNull someParameter) { }

si usted escribe algo como:

someMethod(null);

Esto no compilará.

El último ejemplo de uso de @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Haciendo esto

iWantToDestroyEverything().something();

Y usted puede estar seguro de que esto no ocurra. :)

Es una buena manera de dejar que el compilador de verificación algo más de lo que normalmente lo hace y para hacer cumplir sus contratos para ser más fuertes. Por desgracia, no es apoyado por todos los compiladores.

En IntelliJ 10.5 y, se añade soporte para cualquier otro @aceptan valores null @NotNull implementaciones.

http://blogs.jetbrains.com/idea/2011/03/more-flexible-and-configurable-nullublenotnull-annotations/

304voto

myplacedk Puntos 1237

Si los valores null no está permitido

Si su método llamado externamente, empezar con algo como esto:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

En el resto de ese método, usted sabe que no es null.

Si se trata de un método interno (que no es parte de una api), solo documento que no puede ser nulo, y eso es todo. Ejemplo:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

Sin embargo, si su método sólo pasa el valor, y el siguiente método pasa, etc. podía ser problemático. En ese caso, puede que desee comprobar el argumento como el anterior.

Si es null se permite

Esto realmente depende. Si encuentra que a menudo me hacen algo como esto:

if (object == null) {
  // something
} else {
  // something else
}

Así que me rama, y hacer dos cosas completamente diferentes. No es feo fragmento de código, porque realmente necesito hacer dos cosas diferentes dependiendo de los datos. Por ejemplo, si yo trabajo en la entrada, o debo calcular un buen valor por defecto?


Es realmente raro para mí el uso de los signos "if (object != null && ...".

Puede ser más fácil dar ejemplos, si se muestran ejemplos de donde se suele utilizar el lenguaje.

230voto

erickson Puntos 127945

Wow, casi me odio a agregar otra pregunta cuando tenemos 57 diferentes formas de recomendar la NullObject pattern, pero creo que algunas personas interesadas en esta cuestión le gustaría saber que hay una propuesta sobre la mesa para Java 7 para agregar "null-manejo seguro"-una racionalización de sintaxis para si-no-igualdad-null lógica.

El ejemplo dado por Alex Miller se parece a esto:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

La ?. significa sólo de referencia de la izquierda identificador si no es nula, en caso contrario evaluar el resto de la expresión como null. Algunas personas, como Java Posse miembro de la Polla de la Pared y los votantes en Devoxx encanta esta propuesta, pero no es de la oposición también, por motivos que realmente va a fomentar más el uso de null como un valor de centinela.


Actualización: Una propuesta oficial para un null-operario seguro en Java 7 ha sido presentado en virtud del Proyecto de la Moneda. La sintaxis es un poco diferente que el ejemplo de arriba, pero es el mismo concepto.


Actualización: El null-seguro operador de la propuesta no se hacen en el Proyecto de la Moneda. Así, usted no estar viendo esta sintaxis en Java 7.

189voto

thSoft Puntos 5513

Si los valores no definidos no están permitidos:

Puede configurar el IDE de advertir acerca de potencial nulo de eliminar. Por ejemplo. en Eclipse, ver Preferences > Java > Compiler > Errores/Advertencias/Null análisis.

Si los valores no definidos están permitidos:

Si desea definir una nueva API donde los valores no definidos sentido, el uso de la Opción de Patrón (puede ser familiar a partir de los lenguajes funcionales). Tiene las siguientes ventajas:

  • Se indica explícitamente en el API ya sea de entrada o de salida existe o no existe.
  • El compilador obliga a manejar el "indefinido".
  • Opción es una monada, así que no hay necesidad de detallado comprobación de nulos, simplemente usa el mapa/foreach/getOrElse o una similar combinador de utilizar de forma segura el valor (ejemplo).

Java 8 tiene un built-en Optional de la clase (recomendado); para las versiones anteriores, hay biblioteca alternativas, por ejemplo la Guayaba's Optional o FunctionalJavas' Option. Pero al igual que muchos funcional-patrones de estilo, usando la Opción en Java (hasta 8) resultados en bastante repetitivo, que puede reducir el uso de menos detallado de la JVM idioma, por ejemplo. Scala o Xtend.

Si usted tiene que tratar con una API que puede devolver valores nulos, no se puede hacer mucho en Java. Xtend y Groovy tiene el Elvis operador ?: y el nulo-seguro de eliminar operador ?., pero tenga en cuenta que esto devuelve null en caso de una referencia nula, por lo que sólo es "aplaza" el manejo adecuado de null.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X