2009-12-08 18 views
31

Me enfrento a un caso de uso en el que me gustaría declarar un campo static final con una declaración de inicializador que se declara arrojar una excepción marcada. Por lo general, se vería así:Cómo manejar un inicializador de campo final estático que arroja una excepción comprobada

public static final ObjectName OBJECT_NAME = new ObjectName("foo:type=bar");

El problema que tengo es que el ObjectName constructor puede lanzar varias excepciones comprobadas, que no importan (porque me conoces mi nombre es válida, y está bien si falla miserablemente en caso de que no lo sea). El compilador de Java no me deja simplemente ignorar este (ya que es una excepción comprobada), y yo preferiría no recurrir a:

 
public static final ObjectName OBJECT_NAME; 
static{ 
    try{ 
     OBJECT_NAME = new ObjectName("foo:type=bar"); 
    }catch(final Exception ex){ 
     throw new RuntimeException("Failed to create ObjectName instance in static block.",ex); 
    } 
} 

Debido bloques estáticos son muy, muy difícil de leer. ¿Alguien tiene una sugerencia sobre cómo manejar este caso de una manera agradable y limpia?

+0

Mi solución personal es lanzar un 'CheckedExceptionsAreAPainInTheAssSometimesException', que es una excepción en tiempo de ejecución. El programa simplemente se bloqueará. – Airhead

Respuesta

40

Si no te gustan los bloques estáticos (algunas personas no), entonces una alternativa es usar un método estático. IIRC, Josh Bloch lo recomendó (aparentemente no en Java efectivo en una inspección rápida).

public static final ObjectName OBJECT_NAME = createObjectName("foo:type=bar"); 

private static ObjectName createObjectName(final String name) { 
    try { 
     return new ObjectName(name); 
    } catch (final SomeException exc) { 
     throw new Error(exc); 
    } 
} 

O:

public static final ObjectName OBJECT_NAME = createObjectName(); 

private static ObjectName createObjectName() { 
    try { 
     return new ObjectName("foo:type=bar"); 
    } catch (final SomeException exc) { 
     throw new Error(exc); 
    } 
} 

(Editado:. Corregido segundo ejemplo para regresar de método en lugar de asignar el static)

+2

No lo pensé, a pesar de que lo leí, estoy 100% seguro de haber usado este enfoque hace mucho tiempo. Usaré esto ya que no me gustan los bloques estáticos y también me gusta que mi código sea legible para principiantes (nunca se sabe quién mantendrá tu código después de ti :)). – Romain

+0

me da un error de compilación de "debe devolver un resultado de tipo ObjectName" - ¿sería una solución simple tener 'return null' en el bloque' catch'?Pero luego un poco extraño para depurar – mmcrae

+0

Creo que te refieres al Ítem 59: Evita el uso innecesario de las excepciones marcadas (Effective Java, 2nd Edition). En ese artículo, Bloch está asesorando al autor del código que arroja una excepción para que considere si los clientes pueden tomar alguna acción útil una vez confrontada con la excepción ". Eso es diferente de este caso, donde la pregunta no es la legitimidad de la excepción lanzada, sino la mejor forma de manejar la excepción. Al mirar la documentación de 'java.lang.Error', tengo la sensación de que lanzar un error no es lo mejor que puedo hacer aquí. – nullstellensatz

5

static bloques no son difíciles de leer. Así que recomendaría esa solución. Sin embargo, puede ajustar su objeto en otro objeto, por ejemplo ObjectNameWrapper que comparte un interface con su ObjectName, y cuyo constructor llama al constructor ObjectName, ocultando todas las excepciones marcadas que se producen. Pero de nuevo, elegiría la opción estática.

+2

Introducir otro objeto parece obtuso. –

+1

Estoy de acuerdo con usted. Su sugerencia de método estático es mucho mejor. – Bozho

16

Su código es perfectamente válido. No me resulta difícil leer. Otras formas solo lo empeorarían. Para empezar son difíciles de leer, porque la mayoría de ellos no están familiarizados con eso. Simplemente siga las convenciones estándar con respecto al orden de los elementos en el código. P.ej. no coloque inicializadores estáticos a la mitad o en la parte inferior del código y tampoco tenga varios de ellos extendiéndose sobre la clase. Simplemente ponga uno en la parte superior, después de las declaraciones estáticas.

+0

Este es un punto muy válido (así que lo voté a pesar de no aceptarlo), y el GPP también está mejor indicado. No utilizaré ese método porque, como dices, esto solo es difícil de entender/leer para principiantes ... Y no puedo asegurar que las personas que lo mantendrán después de mí tengan experiencia :). – Romain

+0

No estoy seguro de si preferiría eso. Con la refactorización en un método 'privado estático ', corre el riesgo de perder la supervisión. La práctica normal es que ese tipo de métodos (métodos de utilidad) se colocan en la parte inferior de la clase. Pero está bien, hoy tienes IDE para que puedas hacer clic adelante. – BalusC

Cuestiones relacionadas