2012-01-09 18 views
5

Tengo un método que tiene un Set de objetos. Un método al que delega requiere que el Set no contenga ningún elemento nulo. Me gustaría check the precondition que el Set no contiene elementos nulos temprano, en el método antes de la delegación. El código obvia no hacerlo es la siguiente:Manera aseada de comprobar si un conjunto no contiene un nulo

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } else if (plugIns.contains(null)) { 
     throw new NullPointerException("plugIns null element"); 
    } 
    // Body 
} 

Pero esto es incorrecto, porque Set.contains() puede lanzar una NullPointerException si el Set aplicación en sí no permite elementos nulos. La captura luego ignorando el NullPointerException en ese caso funcionaría but would be inelegant. ¿Hay alguna manera clara de verificar esta condición previa?


¿Existe un error de diseño en la interfaz Set? Si una implementación Set nunca puede contener un valor nulo, ¿por qué no necesita para devolver siempre false? ¿O tiene un predicado isNullElementPermitted()?

+0

Si tiene un requisito específico como este, la subclase 'Establecer' y no permitir 'poner nulo'. Además, no usaría el 'else' aquí. –

Respuesta

4

La manera más simple sería enumerar el conjunto y verificar nulos.

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    for (PlugIn plugIn : plugIns) { 
    if (plugIn == null) throw new NullPointerException("plugIns null element"); 
    } 
} 
+0

Simple, pero 'O (N)' en complejidad, lo que es malo para una comprobación previa. – Raedwald

+0

Para citar a otro: "La preoptimización es la raíz de todo mal". ¿Estás seguro de que esto es un cuello de botella de rendimiento? Dado lo que estás haciendo, supongo que hay un problema arquitectónico en otro lado. –

+0

Mi preocupación es la optimización * no * prematura. Una solución ordenada debe ser de propósito general y razonablemente eficiente. Cada vez que alguien utiliza un 'HashSet' sin primero medir el rendimiento, y obtener el beneficio de' Set.contains() 'rápido, no están realizando una optimización prematura. http://programmers.stackexchange.com/questions/79946/what-is-the-best-retort-to-premature-optimization-is-the-root-of-all-evil. – Raedwald

3

Crear un HashSet de plugIns y comprobar la existencia de null

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) throw new NullPointerException("plugIns"); 
    Set<PlugIn> copy = new HashSet<PlugIn>(plugIns); 
    if (copy.contains(null)) { 
     throw new NullPointerException("null is not a valid plugin"); 
    } 
} 
+0

Simple, pero 'O (N)' en complejidad y crea un nuevo objeto, lo cual es malo para una verificación previa. – Raedwald

+1

¿Cuántas mil veces por segundo escanea en busca de nuevos complementos? ;) En mi experiencia, copiar o crear nuevas colecciones rara vez es un problema de rendimiento. Tal vez deberías evitar que 'null' se agregue de donde viene' plugIns' (para mí suena como si estuvieras arreglando el código erróneo de otra persona, a menos que exista una razón válida para la existencia de un complemento 'null') – Matt

+0

No estoy haciendo esto para solucionar el error del código. Quiero hacerlo porque es mejor detectar fallas temprano. Imagine que se trata de un método de API: no controlaríamos el código de llamada, pero es posible que deseemos proporcionar un buen diagnóstico. – Raedwald

2

Sólo coger el NullPointerException si se tiran e ignorarlo:

public void scan(Set<PlugIn> plugIns) { 
    if (plugIns == null) { 
     throw new NullPointerException("plugIns"); 
    } 

    NullPointerException e = null; 
    try { 
     if (plugIns.contains(null)) { 
      // If thrown here, the catch would catch this NPE, so just create it 
      e = new NullPointerException("plugIns null element"); 
     } 
    } catch (NullPointerException ignore) { } 

    if (e != null) { 
     throw e; 
    } 
    // Body 
} 

Esto crea sólo una sobrecarga menor si lanzados, pero si no usas la excepción (especialmente el rastro), en realidad es bastante liviano.

+0

¿No crees que tus candidatos a NPE son más candidatos de IllegalArgumentException? – Prakhar

Cuestiones relacionadas