traducir - try catch nullpointerexception java




¿Debería un método de recuperación devolver 'nulo' o lanzar una excepción cuando no puede producir el valor de retorno? (20)

Aquí hay un par de sugerencias más.

Si devuelve una colección, evite devolver un valor nulo, devuelva una colección vacía, lo que hace que la enumeración sea más fácil de manejar sin un control nulo primero.

Varias API de .NET utilizan el patrón de un parámetro thrownOnError que le da a la persona que llama la opción de si realmente es una situación excepcional o no si no se encuentra el objeto. Type.GetType es un ejemplo de esto. Otro patrón común con BCL es el patrón TryGet donde se devuelve un valor booleano y el valor se pasa a través de un parámetro de salida.

También puede considerar el patrón de Objeto nulo en algunas circunstancias, que puede ser un valor predeterminado o una versión sin comportamiento. La clave es evitar las comprobaciones nulas en todo el código base. Consulte aquí para obtener más información http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

Tengo un método que se supone que devuelve un objeto si se encuentra.

Si no se encuentra, debo:

  1. retorno nulo
  2. lanzar una excepción
  3. otro

Como regla general, si el método siempre debe devolver un objeto, vaya con la excepción. Si anticipa el nulo ocasional y quiere manejarlo de cierta manera, vaya con el nulo.

Hagas lo que hagas, te recomiendo que no realices la tercera opción: devolver una cadena que diga "WTF".


Desafortunadamente, JDK es inconsistente, si intenta acceder a una clave no existente en el paquete de recursos, no obtiene una excepción y cuando solicita un valor del mapa, obtiene un valor nulo si no existe. Así que cambiaría la respuesta del ganador a la siguiente, si el valor encontrado puede ser nulo, luego generar una excepción cuando no se encuentre, de lo contrario, devuelva nulo. Entonces, siga la regla con una excepción, si necesita saber por qué no se encuentra el valor, siempre genere la excepción, o ...


Devuelva un nulo en lugar de lanzar una excepción y documente claramente la posibilidad de un valor de retorno nulo en la documentación de la API. Si el código de llamada no respeta la API y busca el caso nulo, lo más probable es que resulte en algún tipo de "excepción de puntero nulo" de todos modos :)

En C ++, puedo pensar en 3 tipos diferentes de configuración de un método que encuentra un objeto.

Opción A

Object *findObject(Key &key);

Devuelve nulo cuando no se puede encontrar un objeto. Agradable y sencillo. Yo iría con este. Los enfoques alternativos a continuación son para las personas que no odian a los extraños.

Opción B

void findObject(Key &key, Object &found);

Pase una referencia a la variable que recibirá el objeto. El método arrojó una excepción cuando no se puede encontrar un objeto. Esta convención probablemente sea más adecuada si realmente no se espera que no se encuentre un objeto; por lo tanto, se lanza una excepción para indicar que se trata de un caso inesperado.

Opción C

bool findObject(Key &key, Object &found);

El método devuelve false cuando no se puede encontrar un objeto. La ventaja de esto sobre la opción A es que puede verificar el caso de error en un paso claro:

if (!findObject(myKey, myObj)) { ...

En algunas funciones agrego un parámetro:

..., bool verify = true)

Verdadero significa lanzar, falso significa devolver algún valor de error de retorno. De esta manera, quien use esta función tiene ambas opciones. El valor predeterminado debe ser verdadero, para el beneficio de aquellos que se olvidan del manejo de errores.


En general, debe devolver nulo. El código que llama al método debe decidir si lanzar una excepción o intentar algo más.


Estoy de acuerdo con lo que parece ser el consenso aquí (devolver un valor nulo si "no se encuentra" es un posible resultado normal, o lanzar una excepción si la semántica de la situación requiere que el objeto siempre se encuentre).

Sin embargo, existe una tercera posibilidad que podría tener sentido dependiendo de su situación particular. Su método podría devolver un objeto predeterminado de algún tipo en la condición "no encontrado", permitiendo que el código de llamada tenga la seguridad de que siempre recibirá un objeto válido sin la necesidad de verificación nula o captura de excepción.


Las excepciones deben ser excepcionales . Devuelve nulo si es válido devolver un nulo .


No piense que nadie mencionó la sobrecarga en el manejo de excepciones: requiere recursos adicionales para cargar y procesar la excepción, por lo que, a menos que sea un evento de detención de la aplicación o de detención del proceso real (seguir adelante causaría más daño que bien) optaría por devolver una Valorar el entorno que llama podría interpretar como mejor le parezca.


O devolver una opción

Una opción es básicamente una clase de contenedor que obliga al cliente a manejar los casos de stand. Scala tiene este concepto, busca su API.

Luego tiene métodos como T getOrElse (T valueIfNull) en este objeto para devolver el objeto encontrado o una alternativa a las especificaciones del cliente.


Prefiero volver nulo -

Si la persona que llama lo usa sin verificar, la excepción ocurre allí mismo de todos modos.

Si la persona que llama realmente no lo usa, no le cobres impuestos por un bloque try / catch


Sea consistente con la API (s) que está utilizando.


Si es importante que el código del cliente sepa la diferencia entre lo que se encuentra y lo que no se encuentra y se supone que este es un comportamiento de rutina, entonces es mejor devolver el valor nulo. El código del cliente puede decidir qué hacer.


Si está utilizando una biblioteca u otra clase que lanza una excepción, debe volver a lanzarla . Aquí hay un ejemplo. Example2.java es como una biblioteca y Example.java usa su objeto. Main.java es un ejemplo para manejar esta excepción. Debe mostrar un mensaje significativo y (si es necesario) un seguimiento de la pila para el usuario en el lado de la llamada.

Main.java

public class Main {
public static void main(String[] args) {
    Example example = new Example();

    try {
        Example2 obj = example.doExample();

        if(obj == null){
            System.out.println("Hey object is null!");
        }
    } catch (Exception e) {
        System.out.println("Congratulations, you caught the exception!");
        System.out.println("Here is stack trace:");
        e.printStackTrace();
    }
}
}

Ejemplo.java

/**
 * Example.java
 * @author Seval
 * @date 10/22/2014
 */
public class Example {
    /**
     * Returns Example2 object
     * If there is no Example2 object, throws exception
     * 
     * @return obj Example2
     * @throws Exception
     */
    public Example2 doExample() throws Exception {
        try {
            // Get the object
            Example2 obj = new Example2();

            return obj;

        } catch (Exception e) {
            // Log the exception and rethrow
            // Log.logException(e);
            throw e;
        }

    }
}

Ejemplo2.java

 /**
 * Example2.java
 * @author Seval
 *
 */
public class Example2 {
    /**
     * Constructor of Example2
     * @throws Exception
     */
    public Example2() throws Exception{
        throw new Exception("Please set the \"obj\"");
    }

}

Si siempre está esperando encontrar un valor, lance la excepción si falta. La excepción significaría que había un problema.

Si el valor puede faltar o estar presente y ambos son válidos para la lógica de la aplicación, devuelva un valor nulo.

Más importante: ¿Qué haces en otros lugares en el código? La consistencia es importante.


Siempre que se suponga que devuelva una referencia al objeto, devolver un valor NULL debería ser bueno.

Sin embargo, si está devolviendo todo el asunto sangriento (como en C ++ si lo hace: 'return blah;' en lugar de 'return & blah;' (o 'blah' es un puntero), entonces no puede devolver un NULL, porque es No es del tipo 'objeto'. En ese caso, lanzar una excepción o devolver un objeto en blanco que no tenga un conjunto de indicadores de éxito es la forma en que abordaría el problema.


Solo pregúntese: "¿es un caso excepcional que el objeto no se encuentra"? Si se espera que suceda en el curso normal de su programa, probablemente no debería generar una excepción (ya que no es un comportamiento excepcional).

Versión corta: use excepciones para manejar el comportamiento excepcional, no para manejar el flujo normal de control en su programa.

-Alan


Solo quería recapitular las opciones mencionadas anteriormente, lanzando algunas nuevas en:

  1. retorno nulo
  2. lanzar una excepción
  3. utilizar el patrón de objeto nulo
  4. proporcione un parámetro booleano a su método, para que la persona que llama pueda elegir si desea que lance una excepción
  5. proporcione un parámetro adicional, de modo que el llamante pueda establecer un valor que recupere si no se encuentra ningún valor

O podrías combinar estas opciones:

Proporcione varias versiones sobrecargadas de su receptor, para que la persona que llama pueda decidir qué camino tomar. En la mayoría de los casos, solo el primero tiene una implementación del algoritmo de búsqueda, y los otros simplemente envuelven el primero:

Object findObjectOrNull(String key);
Object findObjectOrThrow(String key) throws SomeException;
Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
Object findObjectOrDefault(String key, Object defaultReturnValue);

Incluso si elige proporcionar solo una implementación, es posible que desee utilizar una convención de nomenclatura como esa para aclarar su contrato, y le ayuda si alguna vez decide agregar otras implementaciones también.

No debe abusar de él, pero puede ser útil, especialmente cuando escribe una clase auxiliar que usará en cientos de aplicaciones diferentes con muchas convenciones diferentes de manejo de errores.


Ventajas de lanzar una excepción:

  1. Flujo de control más limpio en su código de llamada. La comprobación de nula inyecta una rama condicional que se maneja de forma nativa mediante try / catch. La comprobación de nulo no indica qué es lo que está comprobando; está comprobando si está buscando un error que está esperando, o está comprobando si está nulo, por lo que no lo pasa más allá en el downchain ?
  2. Elimina la ambigüedad de lo que significa "nulo". ¿Es nulo representativo de un error o es nulo lo que realmente se almacena en el valor? Es difícil decirlo cuando solo tienes una cosa para basar esa determinación.
  3. Mejor consistencia entre el comportamiento del método en una aplicación. Las excepciones suelen estar expuestas en las firmas de métodos, por lo que es más capaz de comprender en qué casos de borde los métodos de una cuenta de aplicación y a qué información puede reaccionar su aplicación de manera predecible.

Para obtener más explicaciones con ejemplos, consulte: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/


depende de si su lenguaje y código promueven: LBYL (vea antes de saltar) o EAFP (más fácil pedir perdón que permiso)

LBYL dice que debes verificar los valores (devuelve un valor nulo)
EAFP dice que solo intente la operación y vea si falla (lance una excepción)

aunque estoy de acuerdo con lo anterior ... las excepciones deben usarse para condiciones de error / excepcionales, y devolver un nulo es mejor cuando se usan cheques.

EAFP vs. LBYL en Python:
http://mail.python.org/pipermail/python-list/2003-May/205182.html ( archivo web )





null