2012-06-03 19 views
5

Si tengo debajo de la función, con dos opcioneslanzar una excepción o devolver null

private MyObject findBlank() { 
    for (int i = 0; i < pieces.length; i++) { 
     if(pieces[i].isBlank()){ 
      return pieces[i]; 
     } 
    } 
    return null; 
} 

private MyObject findBlank() { 
    for (int i = 0; i < pieces.length; i++) { 
     if(pieces[i].isBlank()){ 
      return pieces[i]; 
     } 
    } 
    throw new NoSuchFieldError("No blank piece found!"); 
} 

Desde este método Sé que siempre debe devolver un objeto una de las piezas '' es siempre isBlank() == true, el retorno nulo al final es solo para complacer al compilador. Dado que este es el caso y mi código no funcionaría de todos modos si devuelve nulo, ¿es correcto hacer una excepción?

Mis opciones son:

  1. retorno nulo y la aplicación obtendrá una NullPointerException en algún caso extremo
  2. devuelto nulo y envolver el uso del método con comprueba
  3. (myObject! = Null) lanzar una excepción que explotará en el tiempo de ejecución

Supongo que lo que estoy preguntando es, ¿es este el lugar correcto para lanzar una excepción? es decir, no hay nada que pueda hacer al respecto si se mete en la situación. ¿Está clasificado como 'excepcional' o no debería verificar qué devuelve mi método (lo que hace que mi código se vea horrible). Si sé que no debería devolver nulo, entonces debería lanzar la excepción ¿no?

Además, ¿cómo podría elegir qué excepción, o extender una y lanzar la mía?

+0

Para ayudar a elegir una excepción: http://wuhrr.wordpress.com/2007/11/22/java-exceptions-list/ – Blundell

+0

¿La sugerencia "ninguno" no es atractiva? :-) – missingfaktor

+0

@missingfaktor Estoy codificando en Android, así que no puedo traer otros frameworks pesados ​​ – Blundell

Respuesta

4

acerca de sus opciones, pregúntese si

  1. ¿Es una buena idea tener su programa de estallar en algún momento después de este método devuelve un valor inesperado (es decir null)?
  2. ¿Qué se ocultará exactamente si enmascara el valor de retorno null?
  3. ¿Es una buena idea explotar inmediatamente, solo porque haya un valor incorrecto?

Personalmente, optaría por la opción 2 o 3, dependiendo de si me gusta la respuesta a la pregunta 2 o 3 mejor. La opción 1 definitivamente es una mala idea, especialmente si no se supone que suceda. Si el programa arroja un método NPE después de que se devuelva la función, tendrá dificultades para averiguar de dónde vino el null. Especialmente si sucede meses después de que termine de trabajar en esta función en particular.

Si decide lanzar una excepción, se ve inmediatamente donde algo salió mal y se puede ir directamente allí para averiguar qué que salió mal. Devolver null y verificarlo en la función de llamada también podría funcionar, pero solo si no falla en silencio, sino que realmente hace algo para manejar el problema correctamente.

4

Sí, debe arrojar un RuntimeException para indicar una situación "excepcional" que no debería haber ocurrido. IllegalStateException probablemente encaja bien. Asegúrese de incluir un mensaje con cualquier información que lo ayude a encontrar el error si alguna vez lo arroja.

+0

No estoy seguro de estar de acuerdo con la parte "no se puede recuperar". –

+0

@HovercraftFullOfEels - ¿Cómo recomiendas que se deba redactar? –

+0

Quitaría la parte "desde la cual su programa no puede recuperar". –

10

Supongo que lo que estoy preguntando es, ¿es este el lugar correcto para lanzar una excepción?

Si se tratara de una situación excepcional , entonces sí. Si la posibilidad de no encontrar nada que coincida con los criterios es esperado, entonces la situación no es excepcional y debe devolver null.

0

siempre debe devolver un objeto o nula rentabilidad
y
la aplicación obtendrá una NullPointerException en algunos casos borde
los dos son contradictorias.

Si está realmente seguro de que usted tiene alwasy pieces[i].isBlank() luego tirar IllegalStateException

otra manera manejar el caso de acuerdo a sus necesidades.

0

si su matriz siempre debe tener un valor válido para devolver, debe plantear una excepción como una alternativa. (Caso 2sd en su ejemplo)

Eventualmente, puede declarar su propio tipo (Clase) de excepción.

0

Sugeriría usar Maybe (también conocido como Option) tipo de datos que acabo de mencionar en another answer hace un tiempo.

Este tipo de datos is available en Functional Java.

Uso:

private Option<MyObject> findBlank() { 
    for (int i = 0; i < pieces.length; i++) { 
     if(pieces[i].isBlank()){ 
      return Option.some(pieces[i]); 
     } 
    } 
    return Option.none(); 
} 

Nota al margen:

Su método findBack se puede generalizar a un método que toma un predicado como un argumento, y encuentra y devuelve el primer elemento eso lo satisface

Como era de esperar, Functional Java already has that as well.

Supongamos por un momento que pieces es un . Luego, su método puede ser reescrita como:

private Option<MyObject> findBlank() { 
    return pieces.find(new F1<MyObject, Boolean>() { 
    public Boolean f(MyObject p) { 
     return p.isBlank(); 
    } 
    }); 
} 

Otra nota al margen:

Tal vez el código anterior se ve bastante retorcido. IntelliJ IDEA's "closure folding" can be of some help here.

+0

Encuentra más carne [aquí] (http://goo.gl/E7lQ7). – missingfaktor

0

Puede ser una buena idea usar Null Object pattern.

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

Así que en ese caso usted no tendrá que utilizar las excepciones o devolver null. Siempre puede devolver el objeto tipo de devolución previsto.El truco es que cuando no tiene nada que devolver, en lugar de devolver null o lanzar una excepción, puede devolver el Null object que es del mismo tipo que el tipo de devolución previsto.

Este documentation tiene algunos ejemplos y descripciones. Y tiene un caso similar al tuyo, resuelto por el patrón de diseño.

public class CustomerFactory { 

    public static final String[] names = {"Rob", "Joe", "Julie"}; 

    public static AbstractCustomer getCustomer(String name){ 
    for (int i = 0; i < names.length; i++) { 
     if (names[i].equalsIgnoreCase(name)){ 
     return new RealCustomer(name); 
     } 
    } 
    return new NullCustomer(); 
    } 
} 
+0

https://www.cs.oberlin.edu/~jwalker/nullObjPattern/ – prime

0

Aparte de la mayor parte de las respuestas me gustaría señalar que si rendimiento es su preocupación continuación, Las excepciones son la forma más lenta que volver nula

Tome un vistazo a este código:

class Main { 
    public static void main(String[] args) { 
     testException(); 
     testNull(); 
    } 

    public static void testException() { 
     long st = System.currentTimeMillis(); 
     for(int i=0;i<10000000;i++) { 
      try{ 
       exp(); 
      } catch(Exception e) { 

      } 
     } 
     long et = System.currentTimeMillis(); 
     System.out.println("Time taken with exceptions : "+(et-st)); 
    } 

    public static void testNull() { 
     long st = System.currentTimeMillis(); 
     for(int i=0;i<10000000;i++) { 
      returnNull(); 
     } 
     long et = System.currentTimeMillis(); 
     System.out.println("Time taken with null : "+(et-st)); 
    } 

    public static void exp() throws Exception { 
     throw new Exception(); 
    } 

    public static Object returnNull() { 
     return null; 
    } 
} 

Los resultados en mi máquina son:

Time taken with exceptions : 7526 
Time taken with exceptions : 5 

Si la excepción de lanzamiento es una condición rara en su código y no ocurrirá con frecuencia, el tiempo tomado en ambas situaciones es casi el mismo.

Tendrás que hacer Rendimiento vs Mantenibilidad/legibilidad trade off.

Lea más sobre esto here

0

nula devolver la mayor parte del tiempo se señalará a la información perdida de la vista contrato, el consumidor no puede saber lo que es la razón de la respuesta equivocada si conseguir la nula del fabricante.

buscando su primer código, hay dos situación, el código externo obtener el NullPointerException: 1. Las piezas es nula 2. Las piezas no tienen tal elemento

Así retorno será nula mis-conducen el exterior código para una operación posterior, generará un problema potencial.

Y hablar de la diferencia entre return nullObject (not null) y excepción, la principal diferencia es PROBABILITY, que significa: 1. Si la situación vacía es mucho más probable, debería devolver nullObject para que TODO código externo pueda/debería manejarlos explícitamente. 2. Si la situación de vacío es menos probable, ¿por qué no lanzar la excepción para que la función de llamada final pueda manejarla directamente?

Cuestiones relacionadas