variable uso parametros modificador metodo diferencia clase java exception constants final

uso - Problemas al inicializar una variable final en Java



uso del final en java (5)

En la misma línea que el problema del OP, tuve que poder encontrar una manera de asignar valores a los campos finales para leerlos desde un archivo .properties en el sistema de archivos, por lo que mi aplicación no podía conocer los valores hasta que sucedió El uso de una llamada de método generalizada para asignar el valor después de leer el contenido del archivo .properties en un objeto de Propiedades en el inicio de la aplicación fue un paso de Hail Mary que afortunadamente funcionó. También limita el no. muchas veces, el archivo debe leerse una vez para que la aplicación se cargue en la memoria simplemente mediante la comprobación del código para ver si el objeto Propiedades es o no está actualmente vacío. Pero, por supuesto, una vez asignado, el valor del campo final no se puede alterar excepto modificando su estado "final" mediante la manipulación de la definición de modificación del campo en tiempo de ejecución (como se explica en otros lugares aquí en SO, como https://stackoverflow.com/a/3301720/1216686 - astuto, pero me encanta!). Ejemplo de código, con la comprobación de errores de tiempo de ejecución típica, como para las NPE omitidas por brevedad:

import java.util.Properties; public class MyConstants { private static Properties props; // declared, not initialized, // so it can still be set to // an object reference. public static String MY_STRING = getProperty("prop1name", "defaultval1"); public static int MY_INT = Integer.parseInt(getProperty("prop2name", "1")); // more fields... private static String getProperty(String name, String dflt) { if ( props == null ) { readProperties(); } return props.getProperty(name, dflt); } private static void readProperties() { props = new Properties(); // Use your fave way to read // props from the file system; a permutation // of Properties.load(...) worked for me. } // Testing... public static void main(String[] args) { System.out.println(MY_STRING); System.out.println(MY_INT); } }

Esto le permite externalizar las propiedades que se leerán en la aplicación y aún marcar los campos utilizados para mantener sus valores como "final". También le permite garantizar un valor devuelto para el valor del campo final ya que getProperty () en la clase Propiedades permite que el código de llamada del método pase un valor predeterminado para usar en caso de que el par clave-valor de la propiedad no se encuentre en el externo archivo .properties.

Sigo encontrando pequeñas variaciones de un problema en Java y está empezando a afectarme, y realmente no puedo pensar en una forma adecuada de solucionarlo.

Tengo una propiedad de objeto que es final, pero dinámica. Es decir, quiero que el valor sea constante una vez asignado, pero el valor puede ser diferente en cada tiempo de ejecución. Así que declaro la variable de nivel de clase al comienzo de la clase, digamos private final FILE_NAME; . Luego, en el constructor, le asigno un valor, por ejemplo, FILE_NAME = buildFileName();

El problema comienza cuando tengo código en el método buildFileName() que lanza una excepción. Así que intento algo como esto en el constructor:

try{ FILE_NAME = buildFileName(); } catch(Exception e){ ... System.exit(1); }

Ahora tengo un error: "Es posible que el campo final en blanco FILE_NAME no se haya inicializado". Aquí es donde empiezo a molestarme un poco con el compilador estricto de Java. Sé que esto no será un problema porque si llega al límite el programa saldrá ... Pero el compilador no lo sabe y, por lo tanto, no permite este código. Si intento agregar una asignación ficticia a la captura, obtengo: "Es posible que el campo final FILE_NAME ya haya sido asignado". Claramente no puedo asignar un valor predeterminado antes del try-catch porque solo puedo asignarlo una vez.

Algunas ideas...?


Pensándolo bien, ¡creo que acabo de encontrar una solución! - Utilice una variable intermedia.

String fileName = null; try{ fileName = buildFileName(); } catch(Exception e){ ... System.exit(1); } FILE_NAME = fileName;

No sé por qué me tomó tanto tiempo pensar en esto ...


Personalmente, solo lanzaría un error: si su flujo de errores está correctamente diseñado, System.exit () debería ser redundante. ¿Es probable que su programa no se arrastre en el desierto si se lanza un error ...?


Qué tal si

String tempName = null; try{ tempName = buildFileName(); } catch(Exception e){ ... System.exit(1); } FILE_NAME = tempName;


Ya sea

try { FILE_NAME = buildFileName(); } catch (Exception e){ ... System.exit(1); throw new Error(); }

O algunos prefieren:

private static final String FILE_NAME = fileName(); private static String fileName() { try { return buildFileName(); } catch (Exception e){ ... System.exit(1); throw new Error(); } }

Pero llamar a System.exit en un inicializador estático es probablemente una mala idea. Va a arruinar las pruebas de su unidad.